2016-09-20 21 views
0

自分自身を複数回呼び出すcudaカーネルを開発中です(動的並列処理)。後続のカーネル呼び出しは、親カーネルが終了した後で実行する必要があります。アルゴリズムは順番に動作します。 EDIT動的並列処理:親カーネルが終了した後に次のカーネルを実行

$ cat turn.cu 
#include <stdio.h> 

__global__ void turnBasedAlgo(int depth, cudaStream_t stream) { 
    if (depth < 3) { 
     printf("depth: %d\n", depth); 
     cudaEvent_t e; 
     cudaEventCreateWithFlags(&e, cudaEventDisableTiming); 
     cudaEventRecord(e, stream); 

     turnBasedAlgo<<<1,1,0,stream>>>(depth+1, stream); 

     cudaStream_t s2; 
     cudaStreamCreateWithFlags(&s2, cudaStreamNonBlocking); 
     cudaStreamWaitEvent(s2, e, 0); 
     turnBasedAlgo<<<1,1,0,s2>>>(depth+1, s2); 

     // some work 
     clock_t start = clock(); 
     clock_t end = clock(); 
     while (end - start < 100000) { 
      end = clock(); 
     } 
    } 
} 

int main(int argc, char **argv) { 
    cudaStream_t s; 
    cudaStreamCreateWithFlags(&s, cudaStreamNonBlocking); 
    turnBasedAlgo<<<1,1,0,s>>>(0, s); 
    cudaDeviceSynchronize(); 
    cudaDeviceReset(); 

    return 0; 
} 
$ nvcc -arch=sm_35 -dc turn.cu && nvcc -arch=sm_35 -link -o turn turn.o 
$ ./turn 
depth: 0 
depth: 1 
depth: 2 
$ nvvp ./turn 

nvvp result

最初の下位呼び出しが親ストリームにカーネルを置くことによって行われます。

はここで、最小限の例です。それはまったく実行されません。 2番目のサブコールは、新しいストリームを作成し、親カーネルが終了したときに記録されるイベントeを待つことによって行われます。このサブコールは直ちに実行されます。

EDIT:子グリッド内で使用する場合のストリームと親グリッドによって作成されたイベントは、未定義の動作を持っているのと同様に、任意のカーネル内で使用された場合の動作は未定義です

ストリームとホスト上に作成されたイベント

。それでも http://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#ixzz4KngEXdsC

で続きを読むターンベースの動的並列処理を実現する方法はありますか?

+1

[mcve] –

答えて

1

CUDA動的並列処理では、厳密に言えば、すべての子カーネルが終了する前に、親カーネルがを終了することはできません。

あなたのケースでは、これの証拠は、部分的に実線(青色)と部分的に中空(白色)であるプロファイラのturnBasedAlgoバーです。これは、親(ホストが起動した)カーネルの全持続時間を表し、中空部分は、親カーネルがそれから生成された子カーネルが終了する間に名目上待機している時間を表します。

この理由はthe programming guideのCDPのセクションに記載されています

そのスレッドによって作成されたすべての子グリッドがしかし、実際には

を完了するまで、親グリッドが完了したと見なされていません子グリッドが終了する前に、親グリッドがすべての「仕事」を完了することが完全に可能である(すなわち、親グリッドスレッドが処理するための命令を持たず、したがって効果的に「リタイア」する可能性がある)。

関連する問題