- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi, the following simple C and Fortran code compiled by Intel C and Fortran compilers gives runtime errors. Could you please take a look? Thank you in advance!
C code:
#include <stdio.h>
#include <omp.h>
#define NBALLS ( 8ULL)
#define MBOXES ( 4ULL)
#define ZERO ( 0ULL)
#define ONE ( 1ULL)
typedef unsigned long long int ui64;
void bb(ui64 nballs, ui64 mboxes, ui64 *n)
{
if (ONE == mboxes) {
#pragma omp atomic
++*n;
} else {
for (ui64 iball = ZERO; iball <= nballs; ++iball)
#pragma omp task default(none) firstprivate(iball, mboxes) shared(n)
bb(iball, mboxes - 1, n);
}
}
int main(void)
{
ui64 n = ZERO;
#pragma omp parallel default(none) shared(n)
#pragma omp single nowait
bb(NBALLS, MBOXES, &n);
printf("n = %llu\n", n);
return 0;
}
Fortran code:
recursive subroutine bb(nballs, mboxes, n)
implicit none
integer(kind = 8), intent(in) :: nballs, mboxes
integer(kind = 8), intent(inout) :: n
integer(kind = 8):: iball
if (1 .eq. mboxes) then
!$omp atomic
n = n + 1
!$omp end atomic
else
do iball = 0, nballs
!$omp task default(none) firstprivate(iball, mboxes) shared(n)
call bb(iball, mboxes - 1, n)
!$omp end task
end do
endif
return
end subroutine bb
program main
use omp_lib
implicit none
integer(kind = 8), parameter :: nballs = 8, mboxes = 4
integer(kind = 8):: n = 0
!$omp parallel default(none) shared(n)
!$omp single
call bb(nballs, mboxes, n)
!$omp end single nowait
!$omp end parallel
print *, "n = ", n
stop
end program main
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Here are feedback from our Developer:
The problem with this test is the shared function parameter. That is:
the function parameter is located on stack;
created OpenMP tasks store address of shared function parameter in order to use it at execution time;
then a thread which created first set of tasks exits the function making stored by tasks stack address invalid;
then, when tasks are executed they access stale memory that may have unspecified value.
Possible fixes:
change: #pragma omp task default(none) firstprivate(iball, mboxes) shared(n)
to: #pragma omp task default(none) firstprivate(iball, mboxes, n)
or add #pragma omp taskwait at the end of "bb" routine making address on pointer "n" valid during tasks execution.
Let us know so that we can close this thread as it's not a compiler bug.
Thanks,
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I am surprised the C code compiled. line 11 has "ui64 *n" and line 19 has ", n)". IOW your call to bb is passing value "n" as opposed to "&n" as does the call to bb at line 29. You should have seen a compile time error as opposed to a runtime error. (though if the compiler did not report an error at compile time, it is likely that at runtime an error would be encountered either hidden or exposed).
The Fortran code is correct as it passes n by reference.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for your reply. But I see no problem in my C code:
- line 11: the last formal argument is a pointer (n is a pointer).
- line 19: the recursive function call passes n, which is a pointer, to bb. (I see no problem.)
- line 29: the actual argument passed to bb is the address of the variable n, which is a pointer.
Therefore, the main function puts the address of n to bb (line 29). Then line 11 gets the address. If only one box remains (line 13), then the counter is incremented (line 15, ++*n; // n stores the address of the variable n in main). Otherwise call bb recursively with the pointer n (line 19 and please note that n stores the address of the variable n in main and it is consistent with line 11).
Hopefully the explanation makes the code clear.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
Thanks for reaching out to us.
>>compiled by Intel C and Fortran compilers
Could you please tell us which C and Fortran compilers you are using to run the codes
Regarding the fortran code, could you please try it using ifx compiler, as it is not showing any run time errors when checked from our end.
>> gives runtime errors
Meanwhile we are looking into this issue internally. we will get back to you soon.
Regards,
Vidya.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi, thank you for the reply!
- the OS is "5.4.0-66-generic #74~18.04.2-Ubuntu SMP"
- the packages of "intel-oneapi-*" version 2021.3.0-3350 is installed via apt-get
I also tried "ifx -qopenmp". Sometimes the executable gives the correct answer (n = 165), but not always.
Thank you again for your effort!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for letting us know this issue. I've reported it to our Developer.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Here are feedback from our Developer:
The problem with this test is the shared function parameter. That is:
the function parameter is located on stack;
created OpenMP tasks store address of shared function parameter in order to use it at execution time;
then a thread which created first set of tasks exits the function making stored by tasks stack address invalid;
then, when tasks are executed they access stale memory that may have unspecified value.
Possible fixes:
change: #pragma omp task default(none) firstprivate(iball, mboxes) shared(n)
to: #pragma omp task default(none) firstprivate(iball, mboxes, n)
or add #pragma omp taskwait at the end of "bb" routine making address on pointer "n" valid during tasks execution.
Let us know so that we can close this thread as it's not a compiler bug.
Thanks,
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi, thanks for your quick response! Your explanation is clear and the fixes work as well.
Normally the shared variable is created by malloc in C or allocate in Fortran and thus it is on the heap. Nevertheless the OpenMP Specification has no requirement for the shared variable, that it must be on the heap or be on the stack. Anyway you can close this thread.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Good catch.
It is the difference between the pointer (C) or reference (Fortran) being shared (not desired) as opposed to that which it points to/references (desired behavior).
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This issue has been resolved and we will no longer respond to this thread. If you require additional assistance from Intel, please start a new thread. Any further interaction in this thread will be considered community only.
Thanks,

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page