• 検索結果がありません。

行列積を用いた性能確認

4.3 OMPCUDA の評価

4.3.1 行列積を用いた性能確認

アプローチ1で述べた通り,行列積はデータ量に対して計算量が多く並列性が高 い問題であり,GPUを用いて高速実行できる問題としても知られている.本アプ

4.3 OMPCUDAの評価 112

ローチでは最大性能を得ることよりも単純な実装で容易に性能を得られることを重 視しているため,単純なループ処理による実装を用いて性能の比較を行った.

本評価における行列積は全て単精度浮動小数の転置なし正方行列に対する行列積 とし,行列の一辺の長さを問題サイズと呼ぶことにする.

評価では以下の実装についての性能比較を行った.

1. OMPCUDA-loop3 : OMPCUDAを用いた,単純な3重ループによる行列積の 実装 (図46)

2. OMPCUDA-loop2 : OMPCUDAを用いた,loop3における外側の2ループを 併合して2重ループとした実装 (図47)

3. SimpleCUDA : SharedMemoryは用いずに各CUDA Threadが行列の各要素を 担当する,CUDAを用いた実装(ソースコード概要を付録1に載せる)

4. UseSharedCUDA : CUDAのサンプルとして提供されているSharedMemoryを 用いた実装(CUDA SDK 2.0付属のサンプルMatrixMulを利用)

5. OmniCPU-loop3 : Omniを用いたループ並列化 (図46をOmniでコンパイル したもの,CPU上で実行,1スレッドから8スレッド)

6. OmniCPU-loop2 : Omniを用いたループ並列化 (図47をOmniでコンパイル したもの,CPU上で実行,1スレッドから8スレッド)

7. AtlasCPU-nothread, AtlasCPU-pthread : ATLASを用いたもの(非スレッド 対応版のAtlasCPU-nothreadとスレッド対応版のAtlasCPU-pthread,いずれ もCPU上で実行)

図48は,問題サイズ1024の行列積に対して,CUDA Thread数をOMPCUDAの デフォルト値である256とした際の各実装の実行時間を示したグラフである.なお CUDAを用いた場合(CUDA-loop3, CUDA-loop2, SimpleCUDA, UseSharedCUDA) の実行時間にはCUDAを初期化するための時間は含まれておらず,CPU-GPU間で のデータ通信時間は含まれている.CUDAの初期化には平均900msec 程度,OM-PCUDAの初期化(CUDAの初期化を含む)の初期化には1600msec程度の時間が必 要であることが確認できている.

4.3 OMPCUDAの評価 113

#define N 1024

f l o a t a [NN] , b [NN] , c [NN ] ;

#pragma omp p a r a l l e l f o r p r i v a t e ( j , k ) f o r( i =0; i<N; i ++){

f o r( j =0; j<N; j ++){ f l o a t tmp = 0 . 0 f ; f o r( k =0; k<N; k++){

tmp += a [ iN+k ] b [ kN+j ] ; }

c [ iN+j ] = tmp ; }

}

図 46: 行列積のソースコード1 (3重ループ)

#define N 1024

f l o a t a [NN] , b [NN] , c [NN ] ;

#pragma omp p a r a l l e l f o r p r i v a t e ( j ) f o r( i =0; i<NN; i ++){

f l o a t tmp = 0 . 0 f ; f o r( j =0; j<N; j ++){

tmp += a [ ( i /N)N+j ] b [ jN+( i%N ) ] ; }

c [ i ] = tmp ; }

図 47: 行列積のソースコード2 (2重ループ)

4.3 OMPCUDAの評価 114

図 48: 行列積の実行時間 1 (問題サイズ 1024)

4.3 OMPCUDAの評価 115

結果を見ると,OMPCUDAはOMPCUDA-loop3とOMPCUDA-loop2で大きく 性能が異なっている.これは3重ループ(OMPCUDA-loop3)の場合には並列度が外側 ループのループ回数である1024であり,CUDA Thread数が256のためCUDA Block 数が1024/256=4という低い並列度で実行されたのに対して,loop2では並列度が 1024*1024,CUDA Thread数が256のためCUDA Block数は1024*1024/256=4096 となり,高い並列度で実行されたことにより性能が向上したものと考えられる.ま たOmniCPUの実行時間を見ると,OmniCPUではCPUのコア数を超える数のス レッドを利用しても性能が向上しないのに対して,CUDAでは物理的な演算器の数 が適切な並列度に直接対応していないことが確認できる.

さらにCUDA-loop2について,問題サイズを1024に保った状態でCUDA Thread 数とCUDA Block数をいくつか変化させた際の実行時間を図49に示す.結果を見 ると,CUDA Thread数は256または512のときに実行時間が短く,CUDA Block 数は多いほど良い性能が得られている.CUDA Block単位での共有メモリである SharedMemoryを用いていないため,並列度が性能を大きく左右するパラメタとなっ ていることがわかる.

以上の結果から,OMPCUDAはGPUの持つ高い並列性を活用したプログラムの 高速化を行えたと言える.