OpenMPプログラミング

■ このスレッドは過去ログ倉庫に格納されています
1デフォルトの名無しさん
垢版 |
NGNG
オフィシャルサイト
http://www.openmp.org/

リンクなどは>>2以下で
161159
垢版 |
2008/08/30(土) 17:17:59
>>160
そうなんだ。Cはバイナリをどうしても読みたいときにいやいや
使う程度だから知らなかったよ。
でもFortranでもmin,max関数はあまり使われないんだけどね。
156のがFortranでよかったら、

unkomin = 1.0e+10
unkomax =-1.0e+10
!$omp paralell do private(i,a) shared(unko)
!$omp& reduction(min:unkomin) reductionmax:unkomax) shared(unko)
do i = 1, 100
a = unko(i)
if (a .LT. unkomin) unkomin = a
if (a .GT. unkomax) unkomax = a
enddo
!$omp end parallel do
write(*,*) unkomin,unkomax

みたいな感じでいけると思うよ。いまコンパイラ使えないからチェックできないけど。
非OpenMPでコンパイルしてもちゃんと動く・・・はず。
162159
垢版 |
2008/08/30(土) 17:19:44
reductionmax は reduction(max ね。
163デフォルトの名無しさん
垢版 |
2008/09/04(木) 22:56:21
2次元配列変数は、reductionで使えないんでしたっけ?
2008/09/07(日) 13:20:49
NG。
ifortは出来た気がする。
2008/09/07(日) 13:26:10
#pragma omp for
#pragma omp parallel for

てなにが違うの?
2008/09/07(日) 17:53:44
#pragma omp for は #pragma omp parallel ブロックの中に書く必要があるが、
parallelブロックにforブロックが1つのことも多いので
#pragma omp parallel for でまとめて書けるようにしてある。
2008/09/09(火) 22:58:56
なるほど。
168デフォルトの名無しさん
垢版 |
2008/09/16(火) 07:09:33
>>143 >>68
スレチな質問で申し訳ないのだけどdllをリンクする設定を
教えて頂けないでしょうか
>>119を参考に
WindowsVista+Visual Studio2005 standardで
Microsoft Windows Software Development Kit for Windows Vistaと
vcredist_x86.exeでReleaseのビルドは通るようになった

>>68を参考に
インストーラーを作ってみたのですが
C\ProgramFiles\Microsoft Visual Studio 8\VC\redistに入ってしまい
winsxsには入ってくれません…
2009/01/21(水) 13:22:31
並列化前後で答えが変わってしまいます。どこがおかしいのでしょうか?

//画像上でランダムで数点選んできた線との距離が最少になる座標を算出
#ifdef _OPENMP
#pragma omp parallel for private(data,x,y,a,b,i,error)
#endif
for(j=0;j<KURIKAWSIKAISUU;j++){
better_error[j] = 1000;//距離初期化
for(y=100;y<=HEIGHT-100;y++){
for(x=100;x<=WIDTH-100;x++){
error = 0;
get_randum_number(data); //ランダムでデータNo.を選択

for(i=0;i<ITIDONIERAZUKAZU;i++){
error += abs(y - a[data[i]]*x - b[data[i]]) / sqrt(1+pow(a[data[i]],2));
}
error /= select;
if(better_error[j] > error){
better_error[j] = error;
ans[j].x = x;
ans[j].y = y;
}
}
}
}
170デフォルトの名無しさん
垢版 |
2009/01/21(水) 14:08:01
よくわかんねけど
get_randum_number
で配列dataにはいる乱数が変わるからじゃね?
たぶん呼ばれる順番が並列と1CPUのときで違うだろうから。

ループ内で乱数つくらないで、でかい乱数用の2次元配列
data0[KURIKAWSIKAISUU][ITIDONIERAZUKAZU]
をループが始まる前に「並列処理しないで」作ってから
(配列data0をshared属性付けて)ループ処理するといいかも。
計算は遅くなりそうだけどね。
171デフォルトの名無しさん
垢版 |
2009/01/21(水) 14:12:47
んでループ内で乱数生成してた部分は
for (i=.....){data[i]=data0[j][i];}
と乱数値の複製に置き換える、と。
172169
垢版 |
2009/01/26(月) 11:03:50
>170
>171
ありがとうございます。
いただいた意見を参考に修正し、できたらご報告します。
2009/01/26(月) 11:33:59
マルチスレッドでrand()使うと全然ランダムじゃないデータが出てくるよ
2009/01/26(月) 12:52:37
rand_r
175デフォルトの名無しさん
垢版 |
2009/02/24(火) 20:57:22
gcc-4.3 で OMP を使い始めました。初心者で正しい使いかたをしている
かどうか判然としません。/proc/cpuinfo で cpufamily 6, model
23 (Harpertown と呼ぶらしい)と表示されるXEONでは確かに速くなるので
すが、cpufamily 15 model 4 (Nocona と呼ぶらしい) では非常に遅くな
ります。これは正しい振る舞いでしょうか。時間は
clock()/CLOCKS_PER_SEC; で測っていますが、これで正しい判断ができる
のでしょうか? 並列化すれば速くなる速度のネックになっている部分を
探す方法はあるのでしょうか? 並列化できるかどうか判然としない部分
を並列化可能なコードに書き直してくれるようなソフトはないでしょうか?

2009/02/24(火) 23:13:22
どうせNoconaの方はデュアルCPU構成じゃなくてしかもHT無効というオチだろ。
2009/02/25(水) 00:35:19
Nocona の /proc/cpuinfo は
processor : 0
..
processor : 3
vendor_id : GenuineIntel
cpu family : 15
model : 4
model name : Intel(R) Xeon(TM) CPU 3.80GHz
stepping : 3
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca
cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx
lm constant_tsc pebs bts nopl pni monitor ds_cpl est tm2 cid cx16 xtpr

となっています
2009/02/25(水) 23:58:19
環境変数 OMP_NUM_THREADS などでスレッド数を指定してますよね。
明示的に指定しないと環境によってスレッド数が1になったりコア数になったりします。

きちんと並列実行できているのに 4-way Nocona で並列性能が出ないとすると
応用依存の問題かと。例えばメモリ帯域幅がネックになっているのかも知れません
(Harpertown ではメモリ帯域幅が足りていて Nocona では足りていないとか)。
どういう計算をしているのかを書くともっと直接的なアドバイスが得られるかもです。

計時の仕方はそれでいいと思います。精度が気になるなら RDTSC について調べると良さげ。

速度のネックになっている部分は、皆目見当がつかないならプロファイラが利用できます。
GCC なら -pg オプション付きでコンパイル、プログラム実行後に gprof コマンドを使って
統計情報を得ます。

時間のかかっている部分が分かったとしてそれを並列化して高速化できるかは別問題。
OpenMP はループを分割して並列化するのがお手軽で効果的ですが、
それができるのはループ間にデータの依存関係がない場合です。
a[i] += a[i-1] のように前後の反復の計算結果を利用したり、
配列の同じ要素に書き込むといった処理がデータ依存性の典型例です。
データ依存関係がある場合はコードを書き換えないと普通は並列化できません。
このあたりは並列プログラミングの普遍的な課題で、対策はケースバイケースです。

自動並列化は研究レベルではよく聞きますが実用的なツールは寡聞にして知りません。
よい自動並列化ツールがあれば私も試してみたいです。
2009/02/26(木) 01:53:54
Intel C++ Compiler 11.0の自動並列化オプション(-parallel)でSPEC CPU 2006のいくつかのベンチマークが高速化しているが
実際のコードでどれだけ役に立つかは使ったことが無いのでわからない
180デフォルトの名無しさん
垢版 |
2009/03/07(土) 23:30:29
OpenMPの効果を調べるため、同じコードを、gfprtranで二通りにコンパイルして実行してみました。
全然速くなりません。むしろ遅くなっています。実行方法やコードが間違っているのでしょうか?
gcc version 4.3.2 (Debian 4.3.2-1.1)

$ gfortran -fopenmp test.o -o test_omp.out
$ time ./test_omp.out
real 9m14.642s
user 3m51.902s
sys 4m22.468s

$ gfortran test.o -o test.out
$ time ./test.out
real 1m15.142s
user 1m14.809s
sys 0m0.340s

CPUは...(/proc/cpuinfoの抜粋)
model name : Intel(R) Pentium(R) D CPU 2.80GHz
cpu MHz : 2793.101
cache size : 1024 KB
cpu cores : 2
181180
垢版 |
2009/03/07(土) 23:32:33
ソースコードは
module ompParam
use omp_lib
implicit none
!integer :: OMP_GET_NUM_THREADS
!integer :: OMP_GET_THREAD_NUM
integer :: myid ! thread ID
end module ompParam

program variation !(coeff, NUM)
!$ use ompParam
implicit none
integer :: i, j, k
integer :: maxI=1000, maxJ=100, maxK=1000
integer :: NUM
double precision, allocatable :: coeff(:,:)
double precision :: alpha ! random number

NUM=1000
allocate( coeff(NUM, maxK) )
coeff(:,:) = 0.0d0
182180
垢版 |
2009/03/07(土) 23:33:54
(続き)
!$omp parallel num_threads(2) private(myid, i, j, k, alpha)
!$ !myid = OMP_GET_THREAD_NUM()
!$ !write(*,*) '(Number of threads in front of do)=', myid

open(unit=100, file='data.bin', form='unformatted', status='unknown')

!$OMP DO
do k = 1, maxK
do j = 1, NUM
do i = 1, maxI
call RANDOM_NUMBER( alpha )
coeff(j,k) = coeff(j,k) + alpha

!$ !myid = OMP_GET_THREAD_NUM()
!$ !write(*,'(3(A4,I3),A37,I2)') 'k=', k, 'j=',j, 'i=', i, 'Number of threads at the end of do:', myid
end do
coeff(j,k) = coeff(j,k) / maxI
write(100) coeff(j,k)
end do
end do

!$omp master
!$ !myid = OMP_GET_THREAD_NUM()
!$ !write(*,*) '(Number of threads after the do)=', myid
!$omp end master
!$omp end parallel
end program variation
183デフォルトの名無しさん
垢版 |
2009/03/08(日) 14:53:53
gfortranは良くしらんけど・・
環境変数で使うCPUの数を指定してみて。
setenv OMP_THREAD_NUM 2
とか。プログラム内で明示しているからいらない気もするけど、まあ
正確にはマニュアルで確認してね。

あとは、I/O(read,write文)はparallel文の外で
するのが吉。この例だと、open(100,....) と write(100)....は
!$omp end parallel
の後でする。ふつうI/OはプライマリのCPUが単独で担当させる方が安全。
同じファイルに複数のプロセスが書き込みしようとすると
順序の保証が無くなるのであとで使いにくいし、書き込みの順番待ちが
発生するのでのろくなる。

乱数代入のループだけなら1/2になっている可能性大。そうなら
作ったコードは一応OpenMPとして動作している・・・と思う。
184180
垢版 |
2009/03/09(月) 17:16:44
>>183
ありがとうございます。実行シェルは作らず、そのまま
$time ./test_omp.out
という風にやっていました。これから実行シェルを作って見ようと思います。

あと、i/oを外に書いたら、確かに一割ほど速くなりました。
でも、それでも圧倒的にOpenMPは遅いです...
185180
垢版 |
2009/03/09(月) 17:18:47
乱数を使わないプログラムだとOKでした!!

~/test$ /bin/csh ./testOMP_exec.sh
Normal version executing...
2.2u 0.0s 0:02.20 100.4% 0+0k 0+1584io 0pf+0w

OpenMP version executing...
2.1u 0.0s 0:01.14 190.3% 0+0k 0+1584io 0pf+0w


資源使用率190%!!乱数発生器がパラレルに対応していなかったようです。
アドバイス、ありがとうございました。
186183
垢版 |
2009/03/10(火) 04:04:33
あ、そっか
乱数生成って種を使いまわすから、並列のときは最初に疑うべきだったね。
あまり役に立たなかったっぽいけど、
とりあえず、おめでとう。
2009/04/19(日) 07:32:44
基本的な質問です。
#pragma omp for
でループを分割してもompを使わないときと差が出ないのですが
もしかしてループの外の資源にアクセスするとき、各スレッドは
排他制御してるってことなんでしょうか。

SSEとかで要素に演算を加えてるだけなんですけど・・・

外から渡された配列とか、mallocしたメモリとか、分割して処理
したいんですが、どこをどういじると改善されるのでしょう?
2009/04/19(日) 09:11:48
>>187
確認だけど #pragma omp for を parallel リージョンで囲んでる?
もし囲んでないなら #pragma omp parallel for としないと並列化されないよ。
2009/04/19(日) 10:08:48
>>188
はい、それはやってます。
中でスレッド数を確認するときちんとコア数分表示されます。
2009/04/28(火) 10:36:42
>>187
外からのメモリは問題ないと思うけど。
ループ間の依存関係がないか、I/Oなど想定外の依存関係がないか、要チェックで。
2009/05/08(金) 04:21:24
OpenMPで並列化することをやってみたのですが、
GCCの方がICCよりも圧倒的に速いのですが、こんなことはよくあるのですか?
ちなみにOptionは

GCC(4.3.2): -O3 -fopenmp -funroll-loops
ICC(11.0.0): -O3 -openmp -openmp -openmp-lib compat

コードはこんな感じのがいくつもあります。
GCCでうひょ早っ!と思ったので、ICCならもっとと思ったのですが、
そうならないのがびっくりです。何かいけないことはありそうでしょうか?
一応どちらも並列化はされており、CPU使用率はほぼ100%になっています。

void func(void){
7 int i,j,k;
8 unsigned char index_x;
9 #pragma omp parallel for private(i,j,k,index_x)
10 for(i=0;i<XS-1;i++){
11 for(j=1;j<YS-1;j++){
12 for(k=1;k<ZS-1;k++){
13
14 index_x = IDX[i][j][k];
15
16 AX[i][j][k] = CX[index_x]*AX[i][j][k]
17 + CLY[index_x]*(BZ[i][j][k]-BZ[i][j-1][k])
18 - CLZ[index_x]*(BY[i][j][k]-BY[i][j][k-1]);
19 }
20 }
21 }
22 }
2009/05/08(金) 04:25:11
>>191
ちなみにCorei7 965での話です。
2009/05/08(金) 09:10:20
>>191
>何かいけないことはありそうでしょうか?
・オプション指定辺り。
・時間の計測方法。

見たところ、gccにはunrollのヒントを与えているのにiccには与えていないように見える。
icc11が標準でunrollしたかどうか、記憶していないが影響があるかも知らん。
それと、gccでもiccでも言えることだがソース全部を見ないことには細かいことは判らん。
例えば、icc -fastでOpenMPを使わない場合の所要時間を測ってみてはどうだろう。

いずれにしても、iccスレ向きのネタになりそうだが。
194デフォルトの名無しさん
垢版 |
2009/05/08(金) 12:03:19
shared属性になる変数を大局変数で指定してるよね?念のため。

ifortだと-O2以上でunrollingはするけどiccだとどうなんだろう。
2009/05/08(金) 23:49:12
ICCなら-QaxSSE4.2くらいは最低限だろう。
2009/05/09(土) 04:30:16
-ax??? /Qax???
ってかえって遅くなること無い?
コードにもよるだろうけど自分のはかえって遅くなるから切ってる
197デフォルトの名無しさん
垢版 |
2009/05/09(土) 07:47:19
結局いろいろなオプションを試してみましたが、 iccはgccには歯が立ちませんでした。
iccは結構高いので、かなりガッカリしてます。orz...
2009/05/09(土) 11:34:06
たしかにlibgompは優秀
SIMD化されてないように思えるのだが

kをOMPによる並列化対象から外して-QxSSE4.2とかってのはどう?
たしかSIMD化とスレッド化は両立できなかったような
2009/05/10(日) 05:00:40
icc の -openmp-lib compat って必須だったけ?
200デフォルトの名無しさん
垢版 |
2009/05/10(日) 05:09:57
追加。
191の例だとcx,cly,clzの要素を参照するときに干渉が起こってそう。
たぶん一次元でそんなに大きくない配列だろうから、添字iとjのループの間で
この3変数をコピーしてみてはどうだろうか?
localcx[n]=cx[n]...みたいな。んでlocalcx, localcly...はprivate属性を付ける。
並列で無い場合には余計な動作だからかえって遅くなりそうだが。
gccはそこをうまくさばいているのかもしれないな。
>>198
お団子ありがとうw
おそらく添字kのループはunrollingの対象になるから、
そのままprivateな並列対象のままで良い気もするけどどうだろう?
201デフォルトの名無しさん
垢版 |
2009/05/10(日) 05:13:51
さらに追加。cx, cly, clz については
CLY[index_x]=CLY[(IDX[i][j][k])]なんだから、
CLY[i][j][k] で表現できると思うんだけど。
暴力的ないい方だけど今ってメモリが青天井に近いから
係数の3次元配列つくってもいいんじゃないかな?

いずれにしてもコードいじるからなあ・・・。gccで幸せならそのまま、という手も。
2009/05/10(日) 21:24:42
そうか
2009/05/11(月) 16:23:48
フリーソフトウェア最高や!
ぷろぷらICCなんか最初からいらんかったんや!
2009/05/12(火) 09:56:25
OpenMPはいざ知らず、普通のプログラムでiccは随分賢いコードを吐くよ。
後はあれだ、MKLのOpenMP対応は生半可じゃなくリニアリティが高い(投入コア数とパフォーマンスがよく比例する)。
2009/05/12(火) 10:55:45
ifortで使ってるけど、16CPUくらいまでならいいよね。
経験的には32個過ぎるあたりからだんだん悪くなる(64CPUでだいたい48CPU相当)けどまあしょうがないか。
それ以上を厳しく要求される計算だとたぶんMPIと自前のソルバの組み合わせになってしまうのかも
しれないけど、まあ普段の用途には16か32倍も出れば御の字だろう。
2009/05/12(火) 18:55:41
OpenMPで16スレッドも使えるようなCPUなんて持ってるのか。羨ましい。
汎用だと4が限界だし
2009/05/12(火) 19:02:43
PCサーバなら、4core*2CPUはざらだと思うが。
# さすがに16とか32は見たことがない……
2009/05/12(火) 19:13:11
cell
209205
垢版 |
2009/05/13(水) 02:45:20
あまり使われていない altix の箪笥が使えるのです。
ふだんは 4core x 2 ですね。Xeon 8コアで、ちと古いItanium16個相当のパフォーマンスは出るので。
2009/05/14(木) 01:08:55
>>201

>>191です。

CLY[index_x]=CLY[(IDX[i][j][k])]はCLYのサイズが小さいため、
2ndキャッシュにキャッシュさせる目的で使っています。

> いずれにしてもコードいじるからなあ・・・。gccで幸せならそのまま、という手も。

これでコードをいじって30%くらい速くなるならやる価値はありそうですが、
おそらくそこまで行くような感じではないように思われます。
あと、GCCでもバージョンによって速さが違いますし、OSが32bitや64bitでも違いました。
「このコンパイラを使えばどの環境でも速くなる!」と言うのはないですかね。
2009/05/14(木) 02:01:54
ハンドアセンブル
2009/05/14(木) 09:53:37
>>210
VTuneは使っている? そのくらいシビアな話なら動的解析してみると何か分かるかもよ。
2009/05/15(金) 01:38:09
VC++2008のStdしか持ってないが
C:\Program Files\Microsoft Visual Studio 9.0\VC\redist\Debug_NonRedist\x86\Microsoft.VC90.DebugOpenMP\vcomp90d.dll
というファイルが入ってる。これ使えるの?
2009/05/15(金) 02:44:45
>>210
非構造格子の格子形状の情報が格納されてるのかな?
それだとidx配列で引くのが不利より有理な点が多そうだね。
だったら200みたいにループの始めでクローン作ったほうがいいかも。
コードもそんなにいじらないだろうし。
>>213
ディレクトリは忘れたけど、その名前のダイナミックリンクライブラリは
使った記憶がある。どういう使いかただったかは忘れた・・・。
215デフォルトの名無しさん
垢版 |
2009/05/21(木) 22:25:36
ちょっと興味があるのだが
OpenMPってこれから並列プログラミングのスタンダードになっていくのかね
MPI+OpenMPのクラスタなんてなかなかだな、環境とプログラムの内容によっちゃあ
2009/05/22(金) 06:56:43
MPI使ったコードを既に持ってるなら、OpenMPはあまりいらないかもな。
OpenMP相当の事は自動並列かなりできるようだしMPI主体が大〜中規模計算の主流で、
マルチ・コアCPUが1〜2個くらいのシステムでお手軽並列が
これからのOpenMPの使いかたになるのではと勝手に予想するw

というかsgiが飛んだり、SUNがソフト屋に買収されたりNECが断念したりで今後のトレンドが読めんね。
217213
垢版 |
2009/06/02(火) 23:51:25
以下の2つのファイルをexeと同じフォルダに入れると使えました。
デバッグビルドでもOpenMPを使えるようです。

C:\Program Files\Microsoft Visual Studio 9.0\VC\redist\Debug_NonRedist\x86\Microsoft.VC90.DebugOpenMP\vcomp90d.dll
C:\Program Files\Microsoft Visual Studio 9.0\VC\redist\Debug_NonRedist\x86\Microsoft.VC90.DebugOpenMP\Microsoft.VC90.DebugOpenMP.manifest
2009/06/23(火) 01:54:45
PriusOnlineでOpenMP/VC8つかってるっぽい
どうしようクアッドコアにしようか
2009/06/23(火) 08:01:00
VC++2010にParallel Pattern Library(PPL)というマルチスレッドライブラリが
追加されるみたいだけどOpenMPとの住み分けはどうなるんだろう。
220デフォルトの名無しさん
垢版 |
2009/06/25(木) 06:30:55
いままでintel fortran 9.1使っていた。お試しで11入れてみた。
オプションはシェフお薦めの
ifort -fast -openmp
だけ。だいたい30%くらい速いようだ。コードにもよるだろうけど、いいね。
というか今までのはなんだったんだw

関係ないけどversion 8は挙動が変だ。なんじゃありゃ。
221デフォルトの名無しさん
垢版 |
2009/06/25(木) 06:31:45
あ、OSはlinux(版はよくわからんw)ね
222デフォルトの名無しさん
垢版 |
2009/06/25(木) 21:51:20
OpenMP3.0使った人いる?
223デフォルトの名無しさん
垢版 |
2009/09/11(金) 06:51:07
OpenMPを使ったループの中でrandを使うと、srandでseedを設定しても、毎回結果が変わってしまいます。
同じ結果を得るようにするにはどうしたらよいでしょうか?
2009/09/11(金) 08:54:45
>>223
スレッドセーフな擬似乱数生成器を使う。
2009/09/11(金) 15:00:32
スレッドセーフなだけじゃ駄目でしょ
226デフォルトの名無しさん
垢版 |
2009/09/12(土) 04:34:20
>>225
kwsk
2009/09/12(土) 04:42:35
実装にもよるんだろうけど、スレッド毎にシードを持つイメージになるんだっけ?
2009/09/12(土) 04:51:43
それ以前の問題で、ループの実行順が一定でないと、同じ乱数列は得られないでしょ。
ループで使う分の乱数を先にテーブルにでも入れておいたら?
2009/09/12(土) 08:18:27
>>228
OpenMPの意味ないじゃん
2009/09/12(土) 08:41:32
スレッドセーフとスレッドセーフじゃないの具体的な例を教えて
2009/09/12(土) 08:43:26
>>223
2009/09/12(土) 08:48:35
>>231
>>223の原因はそれだけじゃないとおもうYO
2009/09/12(土) 08:49:30
スレッドが絡んで意図したとおりに動かないのがスレッドセーフでない状態
234デフォルトの名無しさん
垢版 |
2009/09/12(土) 11:14:56
例えばsin関数は引数のみによって決まるので、スレッドセーフ。
一方、randは内部の状態を保存する変数に各スレッドからどの順序でアクセスされるかによって
結果が変わってくるので、スレッドアウト。
2009/09/12(土) 17:00:44
スレッド・・・アウト・・・??
2009/09/12(土) 18:47:26
きっとスレッドストライク、スレッドボーク、スレッドチェンジなどもあるに違いない。
2009/09/15(火) 01:13:35
!$omp thread out
238デフォルトの名無しさん
垢版 |
2009/09/19(土) 05:24:10
OpenMPとMPIで同じプログラムを書いたら、MPIの方が速かったんですが、どいういうこと??
使っているのは、omp parallel forだけです。
2009/09/19(土) 07:46:38
分散メモリじゃOpenMPはロクに働かないから共有メモリand/orマルチコアだろうけど、
ごくごく一般的に・・・
CPU/Core数が増えるとMPIが早い。OpenMPは効率が頭打ちする。なのでまあ当然ともいえる。
FirstTouchポリシー採用のシステムでは初期化ループで大まかな役割分担を教えてあげないとOpenMPはのろい。
OpenMPで一個でもShareかPrivateかを間違えるor書き忘れると途端に遅くなること有。
一次元配列の分割計算の場合、OpenMPだとUnrollingを抑制するコンパイラも多いのでそうなると結構遅くなる。
・・・などなど。
まあ、OpenMPはお手軽だから中規模な計算がメインな自分は頻繁に使うけど、
カリカリにチューンしたいとか大規模計算になるとMPIのほうが良いよ。
2009/09/19(土) 09:35:41
スレッドの生成の方が、MPIのプロセス間通信より軽いと思っていたのだけど
2009/09/19(土) 21:15:35
iclを使っているんだけど、forの中で初期化したい場合はどうすればいいのかな。

実際はもっともっと複雑なんだけど、イメージ的には下のような感じで
ループの外で共有のtlbを作ってからメインループでtlbを使いたいんだ。
しかし、parallel forの中ではbarrierやsingleが使用出来ない。

かといってtlbのサイズとかループ回数の兼ね合いから、
parallel forをメインループに持っていったりtlbを全スレッド分作るというのは出来れば避けたい。

#pragma omp parallel for
for (int j=0; j<m; ++j)
{
#pragma barrier
#pragma omp single
for (int i=0; i<q; ++i)
{ tlb[i] = foo(i, j); }

#pragma barrier
for (int i=0; i<n; ++i)
{ /* メインの処理 */ }
}
2009/09/19(土) 21:20:22
ミスった。barrierの前にompを付けて読んで下さい。

あとparallel forの中でbarrierやsingleが使用出来ないというのは
コンパイラがハネるという意味です。
OpenMPの仕様を読んでも使えないように読めます。
2009/09/20(日) 00:25:20
>>241
変数 tlb をスレッド間で共有しているのが問題なので、
a) tlb の定義を外側ループの中に移すか、
b) tlb の定義を tlb[スレッド数][q] に変えてスレッドごとに違う tlb[スレッド番号][i] を使う。
2009/09/20(日) 11:09:00
>>243
最初に書いた通り、無論その解決策は理解している上で
tlbのサイズと生成コストの理由から出来れば共有したい、
というのが今回の質問なのですが、OpenMPでは簡単には解決出来ないのでしょうか。

なんでbarrierがforの中で使えないんだろう。
2009/09/20(日) 11:23:57
jのループをparallel forで並行動作させると
たとえばj=0とj=1が同時に存在するよね
にも拘らずtlbを複数用意したくないというのは
tlb[i] = foo(i,0), tlb[i] = foo(i,1)
俺にはついていけない世界だ…
2009/09/21(月) 08:22:43
>>245
ああそうか!
なんて凡ミス、ありがとうございました。
2009/09/23(水) 01:18:05
>>238
なんか変数を各スレッドで共有しているんじゃない?
OpenMPも結構考えないとパフォーマンスは伸びないし、
CPUの利用率も高くなってしまう。
同一マシン上でMPIよりも遅くなるのは考えにくいなあ。
ただ、MPIだと明示的にスレッドを分割しているのに対して、
OpenMPはコンパイラ依存だからね。そういったこともあり得るかも。
2009/09/24(木) 23:57:35
fork-joinのコストがでかい
OpenMPを有効にするとコンパイラ最適化がきかなくなる(・・・というコンパイラが多い)
249デフォルトの名無しさん
垢版 |
2009/09/25(金) 07:43:37
遅くなる原因はこれかな???
http://olab.is.s.u-tokyo.ac.jp/~reiji/openmp.html
2009/10/06(火) 22:47:29
for(i=0;i<N;i++) {
for(j=0;j<N;j++) {
for(k=2;k<N&&i+k<=N&&j+k<=N;k+=2) {
for(n=1;n<=3;n++) {
ごにょ
if(addHash()) {
if((p=getPoint()) == N) goto End;
ごにょ
}
}
ごにょ
}
}
}
}
}
4重ループの中にgoto分使っているけど、こういう場合はどうすればいいの?
251デフォルトの名無しさん
垢版 |
2009/10/07(水) 04:35:58
>>250
gotoを取り除く
2009/10/10(土) 03:19:26
んだ。gotoあると並列処理されにくいよ。
並列化してると、途中で終了するのも最後までやるのも計算コストはかわらんし。
マスクの部分は
if((p=getPoint()) /= N){ごにょ} か if((p=getPoint()) < N){ごにょ}
にする・・・とかかな。
253デフォルトの名無しさん
垢版 |
2009/10/29(木) 11:34:56



岡田外務大臣キタ━━━━━━(゚∀゚)━━━━━━ !!!!!
h‍ttp‍:‍/‍/‍q‍b5.2‍ch.net/t‍est/rea‍d.cgi‍/sak‍u2ch/1256‍630318/1



早く記念カキコしないと埋まっちゃうwww
2009/11/21(土) 02:59:22
OpenMPでスレッド間の1対1通信ってどうやんの
2009/11/23(月) 17:05:30
>>250 >>251
返事遅れてごめん。ありがとう。
2009/11/23(月) 17:07:10
>>252
なるほど。ありがとう。
257デフォルトの名無しさん
垢版 |
2010/01/10(日) 02:26:13
FortranをOpenMPで並列化したのですが、シリアルで実行した場合と結果が変わってしまって困っています。
たぶん共有変数の設定を間違って、書き込んではいけない変数に書き込みが発生してしまったのだと思うのですが、
どう直したらいいのかわかりません。
分かることがあれば教えて下さい。

[並列化したソースコード]http://gaatsu.ps.land.to/up/src/up_1444.png.html
[シリアルで実行した結果]http://gaatsu.ps.land.to/up/src/up_1445.png.html
[パラレルで実行した結果]http://gaatsu.ps.land.to/up/src/up_1446.png.html
z軸のプロットは、ソース中のloss_timeを描いています。
サブルーチンsubの中身は、関係する部分だけ書くと、以下のようになっています。
do i = 1, nend
  t=t+dt
  if (条件)
    loss_time = t
    return
  end if
end do
258デフォルトの名無しさん
垢版 |
2010/01/10(日) 02:29:09
すみません、最後の方で書いた内容、一部間違えました。

サブルーチンsubの中身は、関係する部分だけ書くと、以下のようになっています。
do i = 1, nend
  t=t+dt
  if (条件)
    loss_time = t
    return
  end if
loss_time = t
end do
2010/01/11(月) 10:56:24
多分原因はそこじゃないと思うけれど、共有変数の指定が間違っていると思うなら
privateもsharedも消してdefault(private)にしてみたらいいと思う。

あと基本的な質問だけど
「!$OMP parallel do」ではなくて
「!$OMP parallel」と「!$OMP do」
に分かれている必要性ってあるの?

parallelとdoを分ける文法を普段使わないから挙動が分からないんだけれど、
iのループが分担されずに-(maxGrid-1)から(maxGrid-1)のまま8つ生成されて、
jのループが分担されているのに1つのloss_timeを共有してそうな気がするんだけれど。
2010/01/12(火) 06:07:01
原因はそこじゃないな、おそらくアソコ。
■ このスレッドは過去ログ倉庫に格納されています
5ちゃんねるの広告が気に入らない場合は、こちらをクリックしてください。

ニューススポーツなんでも実況