Frage gfortran openmp kein threading


Ich habe einen einfachen Fortran Code, und trotz der Verwendung der omp_set_num_threads() Subroutine kann ich die Anzahl der Threads nicht festlegen, d. h. die Ausgabe sagt, dass ich nur 1 Thread verwende. Ich habe es auch mit dem versucht export OMP_NUM_THREADS=4 - kein Ergebnis.

Ich habe keine Ahnung, was ist das falsches Stück 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

Die Ausgabe dieses Codes ist:

 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

Danke für jede Art von Tipp!

Ich benutze Gentoo Linux, der GCC-4.5.4 Compiler hat die openmp Flagge aktiviert. Die CPU ist Mobile Core i7 2. 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) 

Ausgabe eines testmp.f140t.optimized (das vor der * .statistik):

;; 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;

}

5
2017-10-25 12:57


Ursprung


Antworten:


Rahmen OMP_NUM_THREADS oder anrufen omp_set_num_threads() setzt die nthreads-var ICV (interne Steuervariable). Um seinen Wert zurückzurufen, sollte man anrufen omp_get_max_threads() und nicht omp_get_num_threads().

Zweitens gibt es in Ihrem Code ein Datenrennen. Standardmäßig behandelt OpenMP beide tnr und t  gemeinsame Variablen. In diesem Fall ist der Wert von tnr angezeigt von der write Anweisung ist der Wert, der im letzten Thread zum Ausführen der Zuweisung erhalten wurde (beachten Sie, dass GCC die Registeroptimierung bei gemeinsamen Variablen unterdrückt).

Der korrekte Code wäre wie folgt:

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

Beachten Sie, dass wenn a do Konstrukt ist sofort und das einzige, was in einem verschachtelt ist parallel Region könnte man die Kombination nutzen parallel do Konstruieren und speichern Sie zwei Codezeilen.


Sie haben Fortran 90-Code in einem gespeichert .f Datei, die daher als feste Quellform erkannt wird. In diesem Fall müssen die OpenMP-Direktiven die folgenden Regeln beachten:

Die folgenden Sentinels werden in Quelldateien mit fester Form erkannt:

!$omp | c$omp | *$omp

Wächter muss in Spalte 1 beginnen und erscheinen als ein einziges Wort ohne dazwischenliegende Zeichen. Die Fortran-Linienlinienlänge, Leerraum-, Folge- und Spaltenregeln gelten für die Anweisungszeile. Die ersten Anweisungszeilen müssen in Spalte 6 ein Leerzeichen oder Null enthalten, und in Zeile 6 müssen Fortsetzungszeilen ein anderes Zeichen als ein Leerzeichen oder eine Null haben. (Betonung meiner)

Ich denke, Ihre Anweisungen beginnen in der gleichen Spalte wie der Rest des Programmcodes und werden daher einfach als Kommentare behandelt und nicht als OpenMP-Direktiven, was sich am Inhalt des testmp.f.140t.optimized Datei.


5
2017-10-25 13:35



Zuerst müssen Sie diesen Code mit kompilieren

gfortran -fopenmp FILE

Die zweite Sache ist, dass omp_get_num_threads() zeigt Ihnen die Anzahl der Threads an der Stelle, wo Sie sind. Wie Sie diese Funktion in einer seriellen Region aufgerufen haben, lautet die Antwort immer 1.


1
2017-10-25 13:17