7

単純な Fortran コードを使用していますが、omp_set_num_threads()サブルーチンを使用しているにもかかわらず、スレッド数を設定できません。つまり、1 つのスレッドしか使用していないと出力に表示されます。私も試してみましたexport OMP_NUM_THREADS=4- 結果はありません。

そのコードの何が悪いのかわかりません:

  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

そのコードの出力は次のとおりです。

 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

あらゆる種類のヒントをありがとう!

私は gentoo Linux を使用しています。gcc-4.5.4 コンパイラではopenmpフラグが有効になっています。CPUはモバイルコアi7第2世代。

ldd テスト:

    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) 

testmp.f140t.optimized の出力 (*.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;

}
4

2 に答える 2

7

設定OMP_NUM_THREADSまたは呼び出しomp_set_num_threads()により、nthreads-var ICV (内部制御変数) が設定されます。その値を取得するにはomp_get_max_threads()、 ではなく を呼び出す必要がありomp_get_num_threads()ます。

次に、コードにデータ競合があります。デフォルトでは、OpenMP はtnrt 共有変数の両方を扱います。その場合、ステートメントtnrによって表示されるwriteの値は、割り当てを実行する最後のスレッドで取得された値になります (GCC は、共有変数に関してはレジスタの最適化を抑制することに注意してください)。

正しいコードは次のようになります。

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

doコンストラクトがすぐに、parallel領域内にネストされた唯一のものである場合、結合されたparallel doコンストラクトを使用して 2 行のコードを節約できることに注意してください。


Fortran 90 コードを.fファイルに保存したため、固定ソース形式として認識されます。この場合、OpenMP ディレクティブは次の規則に従う必要があります。

次のセンチネルは、固定形式のソース ファイルで認識されます。

!$omp| | c$omp| |*$omp

Sentinelは 1 列目から開始し、間に文字を入れずに 1 つの単語として表示する必要があります。ディレクティブ行には、Fortran の固定形式の行の長さ、空白、継続、および列の規則が適用されます。最初のディレクティブ行には、6 列目にスペースまたはゼロが必要であり、継続ディレクティブ行には、6 列目にスペースまたはゼロ以外の文字が含まれている必要があります。

ディレクティブは残りのプログラム コードと同じ列から始まるため、ファイルの内容から明らかなように、OpenMP ディレクティブとしてではなく、単にコメントとして扱われると思いますtestmp.f.140t.optimized

于 2013-10-25T13:35:42.387 に答える