2016-11-11 17 views
0

可能な限り多くのコンピューティングリソースを利用してスプレーマトリックス*高密度ベクトル乗算のGPUで可能な最大スループットを計算しようとしています。cuSparse反復回数が増えるとスループットが低下する

は、これを達成するために、私は2つの方法を試みた:

  1. をホスト上のXとAのためにメモリを割り当てます。ホストにxとAを格納します。デバイスにxとAのメモリを割り当てます。 xとAをデバイスに保存します。タイマーを開始する。ループ内でcusparsecsrmv経由で疎な行列*密ベクトル乗算を実行し、NUM_ITERATIONS回cusparsecsrmvを実行します。タイマーを停止する。 yをデバイスからホストにコピーし、結果が正しいかどうかを確認します。

  2. ホストにxとAのメモリを割り当てます。ホストにxとAを格納します。デバイス上にxとAの配列(x [NUM_IMPS]、A [NUM_IMPS])のメモリを割り当てます。 XとAをデバイスに保存します。タイマーを開始する。ループ内でcusparsecsrmv経由で疎な行列*密ベクトル乗算を実行し、各A [i] * x [i]でNUM_IMPS回cusparsecsrmvを実行します。タイマーを停止する。 y [NUM_IMPS-1]をデバイスからホストにコピーし、結果が正しいかどうかを確認してください。ここで

は、方法1のために私のコードです:ここでは

// == Start timer for just measuring multiplication == 
QueryPerformanceFrequency(&Frequency1); 
QueryPerformanceCounter(&StartingTime1); 


// Sparse matrix * dense vector multiplication 
/* exercise Level 2 routines (csrmv) */ 
for (int i = 0; i < NUM_ITERATIONS; i++) { 
status = cusparseScsrmv(handle, CUSPARSE_OPERATION_NON_TRANSPOSE, m, n, nnz, 
&alpha, descr, cooVal, csrRowPtr, cooColIndex, 
&xVal[0], &beta, &y[0]); 
} 

// == End time for just measuring multiplication == 
QueryPerformanceCounter(&EndingTime1); 
ElapsedMicroseconds1.QuadPart = EndingTime1.QuadPart - StartingTime1.QuadPart; 
ElapsedMicroseconds1.QuadPart *= 1000000; 
ElapsedMicroseconds1.QuadPart /= Frequency1.QuadPart; 

は、方法2のために私のコードです:

// == Start timer for just measuring multiplication == 
QueryPerformanceFrequency(&Frequency1); 
QueryPerformanceCounter(&StartingTime1); 

for (int i = 0; i < NUM_IMPS; i++) { 
status = cusparseScsrmv(handle_array[i], CUSPARSE_OPERATION_NON_TRANSPOSE, m, n, nnz, 
    &alpha, descr_array[i], cooVal_array[i], csrRowPtr_array[i], cooColIndex_array[i], 
    &xVal_array[i][0], &beta, &y_array[i][0]); 
} 

// == End time for just measuring multiplication == 
QueryPerformanceCounter(&EndingTime1); 
ElapsedMicroseconds1.QuadPart = EndingTime1.QuadPart - StartingTime1.QuadPart; 
ElapsedMicroseconds1.QuadPart *= 1000000; 
ElapsedMicroseconds1.QuadPart /= Frequency1.QuadPart; 

NUM_ITERATIONSまたはNUM_IMPS = 1の場合、それらは同じスループットを得ます。 NUM_IMPS = 10の場合、スループットは最大になります。しかし、NUM_IMPS = 100以上になると、スループットが低下し始めます。 は同様NUM_ITERATIONSでそれが増加し始めるが、私は、超大量にNUM_ITERATIONSを設定したら、これが起こっているのはなぜ10万スループットがNUM_ITERATIONS = 1

のスループットの下にドロップしますと言いますか?私はthorughputがちょうどある時点で飽和し、それ以上には行くことができないと期待しますが、は減少しません。

私の考えは、cusparsecsrmvへの複数回の呼び出しにより、GPUが低速化しているか、GPU自体が低速になるため速度が低下するため、スループットは低下しますが、これらはすべて妥当ではないようです私に結論。

答えて

2

documentation:

から引用cuSPARSEライブラリ関数は、ホストへ に関して非同期で実行され、結果の準備ができる前に ホスト上のアプリケーションに制御を戻してもよいです。開発者は cudaDeviceSynchronize()関数を使用して、 特定のcuSPARSEライブラリルーチンの実行が完了していることを確認できます。

タイミングの違い以外は何も問題ありません。現在のところ、ライブラリー呼び出しを実行する時間ではなく、ライブラリー呼び出しをエンキューする時間のみを測定しています。数十または数百の操作がキューに入れば、エンキューのパフォーマンスが低下することを期待するのは完全に合理的です。

+0

タイミングを測定する正しい方法は何ですか?すべての呼び出しの直後にcudaDeviceSynchronize()コマンドを追加しますか?私はそれを実行し、パフォーマンスは、私が期待したよりもはるかに低かった。 – Veridian

+2

パフォーマンスは「タンク」しませんでした。あなたはちょうどそれを正しく測定し始めました。 – talonmies

+0

だから、私はcudaDeviceSynchronizeを実行する前に何回反復して実行すべきだと思いますか?また、引数なしでcudaDeviceSynchronizeを実行するだけですか? – Veridian

関連する問題