我正在编写必须在GTX690(双芯片)板上运行相同内核的代码。由于计算是可分离的,我不需要设备之间的数据交换,我只是将结果合并到CPU上。我了解如何在每个设备上运行代码,以及如何在每个设备的内存空间中提供i / o数据空间。
我在尝试设置常量时遇到问题,两个设备上运行的内核都使用这些常量。我需要为每个设备制作一个阵列吗?如果是这样,我如何在内核中检查哪个设备正在运行,以便从阵列中访问正确的常量?
以下是我正在使用的一些代码。当我仅使用1个芯片时(通过设置numDev = 1
),它可以正常工作,但不能同时使用。
__constant__ float d_cellSizeZ;
std::vector<int*> d_cell;
.................
bool Init(int cellsN_, float size_){
bool res = true;
if(cudaSuccess != cudaGetDeviceCount(&numDev))
return false;
//numDev = 1;
d_cl.resize(numDev);
for(int i = 0; i < numDev; ++i){
res &= (cudaSuccess == cudaSetDevice(i));
if(!res)
break;
res &= (cudaSuccess == cudaMalloc((void**)&d_cell[i], cellsN_*sizef(int)));
};
res &= (cudaSuccess == cudaMemcpyToSymbol(d_cellSizeZ, &size_, sizeof(float)));
if(!res)
Cleanup();
return res;
}
在内核中我只使用d_cellSizeZ
常量。那么,我应该如何为每个设备提供一个常量来从同一个内核中很好地使用呢?
另一个问题是:如果我尝试在设备之间交换数据,它是通过PCI总线还是在双芯片板上存在一些内部路径?
答案 0 :(得分:2)
您只是在最后一台设备上初始化d_cellSizeZ
,因此在其他设备上它将是未定义的。您需要在每个设备上初始化d_cellSizeZ
,最简单的方法是在循环内执行此操作,正如Greg在评论中所建议的那样:
for(int i = 0; i < numDev; ++i)
{
checkCudaErrors(cudaSetDevice(i));
checkCudaErrors(cudaMalloc((void**)&d_cell[i], cellsN_*sizef(int)));
checkCudaErrors(cudaMemcpyToSymbol(d_cellSizeZ, &size_, sizeof(float)));
};
重复使用d_cellSizeZ符号确实有点奇怪。幕后有一点点聪明,但基本上cudaMemcpyToSymbol()
函数在当前活动设备上查找符号,因此每次都复制到正确的设备。