使用独立流在多个GPU上同时调用相同的cuda函数

时间:2012-07-17 13:58:11

标签: cuda

我正在多个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");
}

我的程序可以正常运行两个不同的流,但它按顺序运行。 我想使用两个设备同时使用两个独立的流来运行函数。任何人都可以帮我解决这个问题吗?

我使用两台特斯拉2070与CUDA 4.2合作。

1 个答案:

答案 0 :(得分:2)

您创建的流与您创建它们的上下文相关联,并且在创建它之外的任何上下文中使用流是非法的。在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);
}

根本不需要创建任何流。