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第二代。

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构造并节省两行代码。


您已将 Fortran 90 代码存储在一个.f文件中,因此该文件被识别为固定源格式。在这种情况下,OpenMP 指令必须遵守以下规则:

在固定格式的源文件中可以识别以下标记:

!$omp| c$omp|*$omp

哨兵必须从第 1 列开始,并作为一个单词出现,中间没有字符。Fortran 固定格式行长度、空格、延续和列规则适用于指令行。初始指令行在第 6 列中必须有一个空格或零,而继续指令行在第 6 列中必须有一个空格或零以外的字符。(强调我的

我猜您的指令与程序代码的其余部分在同一列中开始,因此被简单地视为注释而不是 OpenMP 指令,testmp.f.140t.optimized文件内容很明显。

于 2013-10-25T13:35:42.387 回答
1

首先,你必须编译这段代码

gfortran -fopenmp FILE

第二件事是,它会omp_get_num_threads()显示您所在位置的线程数。当您在串行区域中调用此函数时,答案始终是1.

于 2013-10-25T13:17:55.840 回答