1

MKL VSL ライブラリを使用して乱数のベクトルを生成する以下のコードを実装しました。

! ifort -mkl test1.f90 -cpp -openmp

include "mkl_vsl.f90"

#define ITERATION 1000000
#define LENGH 10000

program test
use mkl_vsl_type
use mkl_vsl
use mkl_service
use omp_lib
implicit none 

integer i,brng, method, seed, dm,n,errcode
real(kind=8) r(LENGH) , s
real(kind=8) a, b, start,endd
TYPE (VSL_STREAM_STATE) :: stream
integer(4) :: nt

!     ***** 

brng   = VSL_BRNG_SOBOL
method = VSL_RNG_METHOD_UNIFORM_STD
seed = 777

a = 0.0
b = 1.0
s = 0.0

!call omp_set_num_threads(4)
call omp_set_dynamic(0)
nt = omp_get_max_threads()

!     ***** 

print *,'max OMP threads number',nt

if (1 == omp_get_dynamic()) then
  print '(" Intel OMP may use less than "I0" threads for a large problem")', nt
else
  print '(" Intel OMP should use "I0" threads for a large problem")', nt
end if

if (1 == omp_get_max_threads()) print *, "Intel MKL does not employ threading" 

!call mkl_set_num_threads(4)
call mkl_set_dynamic(0)
nt = mkl_get_max_threads()

print *,'max MKL threads number',nt

if (1 == mkl_get_dynamic()) then
  print '(" Intel MKL may use less than "I0" threads for a large problem")', nt
else
  print '(" Intel MKL should use "I0" threads for a large problem")', nt
end if

if (1 == mkl_get_max_threads()) print *, "Intel MKL does not employ threading"      

!     ***** Initialize *****

      errcode=vslnewstream( stream, brng,  seed )

!     ***** Call RNG *****

start=omp_get_wtime()

do i=1,ITERATION 
      errcode=vdrnguniform( method, stream, LENGH, r, a, b ) 
      s = s + sum(r)/LENGH
end do      

endd=omp_get_wtime()    

!     ***** DEleting the stream *****      

      errcode=vsldeletestream(stream)

!     ***** 

print *, s/ITERATION, endd-start

end program test

たとえば、4 スレッドと 32 スレッドを使用した場合、スピードアップは見られません。
Intel コンパイラ バージョン 13.1.3 を使用してコンパイルします。

ifort -mkl test1.f90 -cpp -openmp

乱数が並行して生成されないようです。
ここにヒントはありますか?

ありがとうございました、

エリック。

4

1 に答える 1

3

コードには、作業を実際に並列化するための OpenMP ディレクティブが含まれていません。実行すると、1 つのスレッドのみが実行されます。use omp_lib関数へのいくつかの呼び出しをあちこちに分散させるだけでは十分ではありませんomp_get_wtime。実際には、いくつかのワークシェアリング ディレクティブを挿入する必要があります。

コードをそのまま実行すると、パフォーマンス モニターはアクティブなスレッドが 1 つだけであることを示し、コードはレポートします。

 max OMP threads number 16
 Intel OMP should use 16 threads for a large problem
 max MKL threads number 16
 Intel MKL should use 16 threads for a large problem
 0.499972674509302 11.2807227574035

このように、ループを OpenMP ワークシェアリング ディレクティブで単純にラップすると、

!$omp parallel do
do i=1,ITERATION 
      errcode=vdrnguniform( method, stream, LENGH, r, a, b ) 
      s = s + sum(r)/LENGH
end do      
!$omp end parallel do

私のデュアルクアッドコアとハイパースレッディングPCのパフォーマンスモニターは、16個のスレッドがアクティブであり、プログラムが報告することを示しています

 max OMP threads number 16
 Intel OMP should use 16 threads for a large problem
 max MKL threads number 16
 Intel MKL should use 16 threads for a large problem
 0.380979220384302 7.17352125150956

私が提供するヒントは次のとおりだと思います。お気に入りの OpenMP チュートリアル、特にparallelおよびdoディレクティブをカバーするセクションを調べてください。私が行った単純な変更があなたのプログラムを壊さないという保証はありません。特に、競合状態が発生していないことを保証するものではありません。

1 から 16 の (ハイパー) スレッドへのスピードアップが許容できるかどうかを判断する演習と、それほど控えめに見える理由の分析はお任せします。

于 2013-12-13T11:56:53.837 に答える