1

複数の GPU にプログラムを実装しています... PC に 2 つの GPU があり、両方のデバイスを処理するために 2 つの独立したストリームを生成したいと考えています。2 つのストリームを生成しました。

cudaStream_t *streams; 
streams = (cudaStream_t*) malloc(nstreams * sizeof(cudaStream_t));
for(int j = 0; j < nstreams; j++){
    cudaStreamCreate(&(streams[j]));
}

次に、SDK の例に従って、デバイス ID をパラメーターとしてカーネルを呼び出そうとします。デバイス ID に従って、cudaDevice が設定され (cudaSetDevice(dev_ID);)、カーネル呼び出しがそれぞれのストリームで渡されます。

kernel1<<< grid, block,0,streamNo >>>(tex, size);................


for (i = 0;i<gpuN;i++){
    initialize(i);
    printf("initialization done with stream %i on device %i\n", (int)streams[i], i);
    runTest(i);
    printf("running tests done with  %i  stream \n", i);
    deini(i);
    printf("deinitialization is done\n");
}

私のプログラムは 2 つの異なるストリームで正常に動作していますが、順次実行されます。両方のデバイスを使用して、両方の独立したストリームを使用して機能を同時に実行したいと考えています。誰でもこの問題を解決するのを手伝ってもらえますか?

2 台の Tesla 2070 を使用して CUDA 4.2 を使用しています。

4

1 に答える 1

3

作成したストリームは、それらを作成したコンテキストに関連付けられており、作成されたコンテキスト以外のコンテキストでストリームを使用することは違法です。CUDA 4.x 以降では、コンテキストの切り替えは を使用して実行されcudaSetDevice()ます。

したがって、これを行うには、次のようにする必要があります。

cudaStream_t *streams[ndevices];

for(int i=0; i<ndevices; i++) {
    cudaSetDevice(i);  
    streams[i] = (cudaStream_t*) malloc(nstreams * sizeof(cudaStream_t)); 
    for(int j = 0; j < nstreams; j++){ 
        cudaStreamCreate(&(streams[j])); 
    }
} 

nstreamsこれにより、列挙された各デバイスでストリームが作成されます[0,..,ndevices-1]。ストリームで操作を実行するとき (カーネルの起動、非同期 memcpy の実行など) は常に、cudaSetDevice()最初に正しいデバイス コンテキストに対して実行する必要があります。

実際には、ストリームをまったく使用する必要がないように思えます。2 つのストリームと 2 つのデバイスしかない場合、メインのカーネル起動コードはおそらく次のように単純になります。

for(int i=0; i<2; i++) {
    cudaSetDevice(i);
    kernel1<<< grid, block >>>(tex, size);
}

実際にストリームを作成する必要はまったくありません。

于 2012-07-17T14:48:05.070 に答える