インテル®コンパイラー OpenMP*入門
デュアルコア・マルチコア対応アプリケーション開発@
<< 16 >>
1 #define num_steps 1000000000
2 double step;
3 main ()
4 { int i; double x, pi, sum = 0.0;
5
6 step = 1.0/(double) num_steps;
7
8 #pragma omp parallel for private(x) reduction(+:sum)
9 for (i=1;i<= num_steps; i++){
10 x = (i-0.5)*step;
11 sum = sum + 4.0/(1.0+x*x);
12 }
13 pi = step * sum;
14 printf (" pi = %f \n",pi);
15 }
このプログラムに対して、OpenMP*での並列化をコンパイラーに指示することで、並列化が可能になります。
Linux* でのコンパイル例と出力を示します。
$ icc -openmp openmp-report2 -O3 sample1.c
sample1.c(8) : (col. 1) remark: OpenMP DEFINED LOOP WAS PARALLELIZED.
OpenMP* での並列化では、自動並列化が 難しい関数やサブルーチンの呼び出しを含むタスクでの並列化 (疎粒度
での並列化) が可能になります。コンパイラーの自動並列化では認識できないこのような粒度の大きな並列化では、
OpenMP* を利用することによりオーバーヘッドの小さな並列化処理が 可能となります。
次の例は OpenMP* ホームページ ( http://www.openmp.org に掲載されているサンプルプログラムです。ここでは
並列実行領域内からサブルーチンを呼び出しています。このようなプログラムコードの粗粒度の並列性を最大限に活
用することで高いスケーラビリティーの実現が 可能となります。
!$omp parallel do
!$omp& default(shared)
!$omp& private(i,j,k,rij,d)
!$omp& reduction(+ : pot, kin)
do i=1,np
! compute potential energy and forces
f(1:nd,i) = 0.0
do j=1,np
if (i .ne. j) then
call dist(nd,box,pos(1,i),pos(1,j),rij,d)
! attribute half of the potential energy to particle 'j'
pot = pot + 0.5*v(d)
do k=1,nd
f(k,i) = f(k,i) - rij(k)*dv(d)/d
enddo
endif
enddo
! compute kinetic energy
kin = kin + dotr8(nd,vel(1,i),vel(1,i))
enddo
!$omp end parallel do
kin = kin*0.5*mass
subroutine dist(nd,box,r1,r2,dr,d)
implicit none
integer i
・・・・
・・・・
d = 0.0
do i=1,nd
dr(i) = r1(i) - r2(i)
d = d + dr(i)**2.
enddo
d = sqrt(d)
return
end
http://www.specbench.org には SPEComp* という OpenMP* によるマルチスレッド・プログラムの標準ベンチマークの結果が 掲載されています。このページに
掲載されている OpenMP* を用いたベンチマーク・コードはいずれも高いスケーラビリティーを示しています。そのコードのほとんどは、 単純なループレベルの
並列化ではなく、より粒度の大きな並列度で並列化されています。