2013-10-25 102 views
5

我有一個簡單的Fortran代碼,儘管使用了omp_set_num_threads()子例程,我無法設置線程數,即輸出說我只使用1個線程。我也嘗試了export OMP_NUM_THREADS=4 - 沒有結果。gfortran openmp no threading

我不知道什麼是錯了,它的代碼,PICE:

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(所述的*。統計前一個)的輸出:

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

} 
+0

你用'gfortran -fopenmp ...'編譯過嗎? – Stefan

+0

適用於gfortran-4.8上的我,除了將't = omp_get_num_threads()'移動到'parallel'區域之外。 –

+0

「tnr」的作品呢? – nykon

回答

5

設置OMP_NUM_THREADS或致電omp_set_num_threads()設置nthreads-var ICV(內部控制變量)。要恢復其值,應該調用omp_get_max_threads()而不是omp_get_num_threads()

其次,代碼中存在數據競爭。默認情況下,OpenMP將同時處理tnrt共享變量。在這種情況下,write語句顯示的tnr的值將是最後一個執行賦值的線程中獲得的值(請注意,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文件的內容顯而易見。

+0

好的建議與「omp_get_max_threads()」。但是「tnr」對於每個「我」仍然顯示「0」。現在我嘗試了kubuntu機器上的代碼,結果仍然如此:/ – nykon

+0

假設您的可執行文件被稱爲'test'。 'libgomp.so'是否顯示在'ldd test'的輸出中? –

+0

期待的職位我已經更新了一些額外的infroamtion。 – nykon

1

在首先,您必須編譯此代碼

gfortran -fopenmp FILE 

第二件事是,omp_get_num_threads()顯示你在哪個點的線程數。當你在一個串行區域調用這個函數時,答案始終是1

+0

我用「-fopenmp」編譯代碼。在循環內部有第二個函數「omp_get_thread_num()」,它應該顯示實際使用線程的數量,所以這個數字從0 ... 3(4個線程)變化,但是正如你在輸出中看到的線程號是總是「0」 – nykon

+0

如果沒有指定'-fopenmp',程序將不會鏈接。 –

+0

@Hristo哪個意思?我怎樣才能指定-fopenmp? – nykon