1

我正在多个 GPU 上实现我的程序...我的 PC 中有两个 GPU,并希望生成两个独立的流来处理这两个设备。我生成了两个流:

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");
}

我的程序在两个不同的流中运行良好,但它是按顺序运行的。我想使用两个设备同时使用两个独立的流来运行功能。谁能帮我解决这个问题?

我正在使用两个 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()到正确的设备上下文。

实际上听起来您可能根本不需要使用流。如果你只有两个流和两个设备,你的主内核启动代码可能很简单:

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

实际上根本不需要创建任何流。

于 2012-07-17T14:48:05.070 回答