我正在写一些CUDA代码。代码是模拟,因此必须运行多次迭代,每次迭代都取决于邻居的结果。由于有很多数据,我决定使用流和平铺。
这是代码的简化方案:
sync = (int *)malloc(tiles * tiles * tiles * sizeof(*sync));
memset(sync, 0, tiles * tiles * tiles * sizeof(*sync));
// At the moment tiles = 4
for (i = 0; i < tiles * tiles * tiles; ++i) {
cudaStreamCreate(&data[i].stream);
data[i].sync = sync;
data[i].tiles = tiles;
data[i].x = i / (tiles * tiles);
data[i].y = (i / tiles) % tiles;
data[i].z = i % tiles;
kernel<<<grid_size, block_size, 0, data[i].stream>>>(/* parameters */);
cudaStreamAddCallback(data[i].stream, cudaCallback, &data[i], 0);
}
// Synchronization and respawn (now trying just 1 iteration, so no respawn)
for (i = 0; i < tiles * tiles * tiles; ++i) {
printf("Waiting %d\n", i);
while (sync[i] != iters) { __sync_synchronize(); }
}
回调:
void CUDART_CB cudaCallback(cudaStream_t stream, cudaError_t status, void *data)
{
struct lifeStreamData *streamData = (struct lifeStreamData *)data;
__sync_fetch_and_add(&streamData->sync[streamData->x * streamData->tiles *
streamData->tiles + streamData->y * streamData->tiles +
streamData->z], 1);
printf("Callback: done tile %d\n", streamData->x * streamData->tiles * streamData->tiles +
streamData->y * streamData->tiles + streamData->z);
}
但这不起作用。仅调用最多55个回调。所以,程序挂在&#34;等待56&#34;。有4个瓦片,所以应该有64个回调。
也许内核运行得太快而无法设置回调?但为什么它适用于55而不是最后9?
内核是正确的(至少它没有挂起),因为它没有平铺正常运行,并且通过参数,可以更改大小和输入数据。
我知道代码不是最佳也不漂亮,但目前我正在努力使这项工作成功,所以我可以从这里进行优化。
答案 0 :(得分:1)
在更改输入到内核的数据大小时,我错过了一个极端情况。这就是失败的原因。它现在正在运作。