I have a simple Fortran code, and despite the use of the omp_set_num_threads()
subroutine, I cannot set number of threads, i.e. the output says that I use only 1 thread. I tried also with the export OMP_NUM_THREADS=4
- no result.
I have no idea what is wrong it that pice of code:
program test
use omp_lib
implicit none
integer :: i, tnr,t
call omp_set_num_threads( 4 )
t = omp_get_num_threads()
write(*,*)'t:',t
!$omp parallel
!$omp do
do i = 1, 20
tnr = omp_get_thread_num()
write( *, * ) 'Thread', tnr, ':', i
end do
!$omp end do
!$omp end parallel
end program test
The output of that code is:
t: 1
Thread 0 : 1
Thread 0 : 2
Thread 0 : 3
Thread 0 : 4
Thread 0 : 5
Thread 0 : 6
Thread 0 : 7
Thread 0 : 8
Thread 0 : 9
Thread 0 : 10
Thread 0 : 11
Thread 0 : 12
Thread 0 : 13
Thread 0 : 14
Thread 0 : 15
Thread 0 : 16
Thread 0 : 17
Thread 0 : 18
Thread 0 : 19
Thread 0 : 20
Thanks for any kind of tip!
I use gentoo linux, the gcc-4.5.4 compiler has the openmp
flag activated. The cpu is mobile core i7 2nd generation.
ldd test:
linux-vdso.so.1 (0x00007fff85fce000)
libgfortran.so.3 => /usr/lib/gcc/x86_64-pc-linux-gnu/4.5.4/libgfortran.so.3 (0x00007fe310460000)
libm.so.6 => /lib64/libm.so.6 (0x00007fe310169000)
libgomp.so.1 => /usr/lib/gcc/x86_64-pc-linux-gnu/4.5.4/libgomp.so.1 (0x00007fe30ff5b000)
libgcc_s.so.1 => /usr/lib/gcc/x86_64-pc-linux-gnu/4.5.4/libgcc_s.so.1 (0x00007fe30fd45000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fe30fb28000)
libc.so.6 => /lib64/libc.so.6 (0x00007fe30f77d000)
librt.so.1 => /lib64/librt.so.1 (0x00007fe30f574000)
/lib64/ld-linux-x86-64.so.2 (0x00007fe310749000)
gfortran -v
Using built-in specs.
COLLECT_GCC=/usr/x86_64-pc-linux-gnu/gcc-bin/4.5.4/gfortran
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-pc-linux-gnu/4.5.4/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: /var/tmp/portage/sys-devel/gcc-4.5.4/work/gcc-4.5.4/configure --prefix=/usr --bindir=/usr/x86_64-pc-linux-gnu/gcc-bin/4.5.4 --includedir=/usr/lib/gcc/x86_64-pc-linux-gnu/4.5.4/include --datadir=/usr/share/gcc-data/x86_64-pc-linux-gnu/4.5.4 --mandir=/usr/share/gcc-data/x86_64-pc-linux-gnu/4.5.4/man --infodir=/usr/share/gcc-data/x86_64-pc-linux-gnu/4.5.4/info --with-gxx-include-dir=/usr/lib/gcc/x86_64-pc-linux-gnu/4.5.4/include/g++-v4 --host=x86_64-pc-linux-gnu --build=x86_64-pc-linux-gnu --disable-altivec --disable-fixed-point --without-ppl --without-cloog --disable-lto --enable-nls --without-included-gettext --with-system-zlib --enable-obsolete --disable-werror --enable-secureplt --enable-multilib --enable-libmudflap --disable-libssp --enable-libgomp --with-python-dir=/share/gcc-data/x86_64-pc-linux-gnu/4.5.4/python --enable-checking=release --disable-libgcj --enable-languages=c,c++,fortran --enable-shared --enable-threads=posix --enable-__cxa_atexit --enable-clocale=gnu --enable-targets=all --with- bugurl=http://bugs.gentoo.org/ --with-pkgversion='Gentoo 4.5.4 p1.0, pie-0.4.7'
Thread model: posix
gcc version 4.5.4 (Gentoo 4.5.4 p1.0, pie-0.4.7)
output of a testmp.f140t.optimized (the one before the *.statistics):
;; Function test (MAIN__)
test ()
{
struct __st_parameter_dt dt_parm.1;
logical(kind=4) D.1545;
struct __st_parameter_dt dt_parm.0;
integer(kind=4) tnr;
integer(kind=4) t;
integer(kind=4) i;
integer(kind=4) i.8;
integer(kind=4) i.7;
integer(kind=4) i.6;
integer(kind=4) tnr.5;
integer(kind=4) i.4;
integer(kind=4) t.3;
<bb 2>:
omp_set_num_threads (&C.1537);
t.3_1 = omp_get_max_threads ();
t = t.3_1;
dt_parm.0.common.filename = &"testmp.f"[1]{lb: 1 sz: 1};
dt_parm.0.common.line = 11;
dt_parm.0.common.flags = 128;
dt_parm.0.common.unit = 6;
_gfortran_st_write (&dt_parm.0);
_gfortran_transfer_character (&dt_parm.0, &"t:"[1]{lb: 1 sz: 1}, 2);
_gfortran_transfer_integer (&dt_parm.0, &t, 4);
_gfortran_st_write_done (&dt_parm.0);
i = 1;
i.4_2 = i;
if (i.4_2 <= 20)
goto <bb 3>;
else
goto <bb 5>;
<bb 3>:
tnr.5_3 = omp_get_thread_num ();
tnr = tnr.5_3;
dt_parm.1.common.filename = &"testmp.f"[1]{lb: 1 sz: 1};
dt_parm.1.common.line = 16;
dt_parm.1.common.flags = 128;
dt_parm.1.common.unit = 6;
_gfortran_st_write (&dt_parm.1);
_gfortran_transfer_character (&dt_parm.1, &"Thread"[1]{lb: 1 sz: 1}, 6);
_gfortran_transfer_integer (&dt_parm.1, &tnr, 4);
_gfortran_transfer_character (&dt_parm.1, &":"[1]{lb: 1 sz: 1}, 1);
_gfortran_transfer_integer (&dt_parm.1, &i, 4);
_gfortran_st_write_done (&dt_parm.1);
i.6_4 = i;
D.1545_5 = i.6_4 == 20;
i.7_6 = i;
i.8_7 = i.7_6 + 1;
i = i.8_7;
if (D.1545_5 != 0)
goto <bb 5>;
else
goto <bb 4>;
<bb 4>:
goto <bb 3>;
<bb 5>:
return;
}
;; Function main (main)
main (integer(kind=4) argc, character(kind=1) * * argv)
{
static integer(kind=4) options.2[8] = {68, 255, 0, 0, 0, 1, 0, 1};
integer(kind=4) D.1552;
<bb 2>:
_gfortran_set_args (argc_1(D), argv_2(D));
_gfortran_set_options (8, &options.2[0]);
test ();
D.1552_3 = 0;
return D.1552_3;
}
Setting OMP_NUM_THREADS
or calling omp_set_num_threads()
sets the nthreads-var ICV (Internal Control Variable). To retrieve back its value, one should call omp_get_max_threads()
and not omp_get_num_threads()
.
Second, there is a data race in your code. By default OpenMP will treat both tnr
and t
shared variables. In that case the value of tnr
displayed by the write
statement will be the value obtained in the last thread to execute the assignment (note that GCC suppresses register optimisation when it comes to shared variables).
The correct code would be as follows:
program test
use omp_lib
implicit none
integer :: i, tnr,t
call omp_set_num_threads( 4 )
t = omp_get_max_threads()
write(*,*)'t:',t
!$omp parallel do private(tnr)
do i = 1, 20
tnr = omp_get_thread_num()
write( *, * ) 'Thread', tnr, ':', i
end do
!$omp end parallel do
end program test
Note that when a do
construct is immediately and the only thing nested inside a parallel
region, one could use the combined parallel do
construct and save two lines of code.
You have stored Fortran 90 code in a .f
file, which is therefore recognised as fixed source form. In this case the OpenMP directives must obey the following rules:
The following sentinels are recognized in fixed form source files:
!$omp
|c$omp
|*$omp
Sentinels must start in column 1 and appear as a single word with no intervening characters. Fortran fixed form line length, white space, continuation, and column rules apply to the directive line. Initial directive lines must have a space or zero in column 6, and continuation directive lines must have a character other than a space or a zero in column 6. (emphasis mine)
I guess your directives start in the same column as the rest of the program code and therefore are treated simply as comments and not as OpenMP directives, evident by the content of the testmp.f.140t.optimized
file.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With