Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

gfortran openmp no threading

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;

}
like image 364
nykon Avatar asked Oct 25 '13 12:10

nykon


1 Answers

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.

like image 130
Hristo Iliev Avatar answered Oct 09 '22 13:10

Hristo Iliev