我正在寻找一种方法来摆脱闲置代码中的主机线程中的忙碌等待(不要复制该代码,它只会显示我的问题,它有很多想法基本的错误):摆脱异步执行期间的繁忙等待
cudaStream_t steams[S_N];
for (int i = 0; i < S_N; i++) {
cudaStreamCreate(streams[i]);
}
int sid = 0;
for (int d = 0; d < DATA_SIZE; d+=DATA_STEP) {
while (true) {
if (cudaStreamQuery(streams[sid])) == cudaSuccess) { //BUSY WAITING !!!!
cudaMemcpyAssync(d_data, h_data + d, DATA_STEP, cudaMemcpyHostToDevice, streams[sid]);
kernel<<<gridDim, blockDim, smSize streams[sid]>>>(d_data, DATA_STEP);
break;
}
sid = ++sid % S_N;
}
}
有没有办法空闲主机线程并以某种方式等待一些流来完成,然后准备和运行另一个流?
编辑:我在代码中添加while(true),强调忙等待。现在我执行所有的流,并检查其中哪些完成了运行另一个新的流。 cudaStreamSynchronize
等待特定的流完成,但我想等待作为第一个完成工作的任何流。
EDIT2:我得到了在休耕的方式摆脱忙等待:
cudaStream_t steams[S_N];
for (int i = 0; i < S_N; i++) {
cudaStreamCreate(streams[i]);
}
int sid = 0;
for (int d = 0; d < DATA_SIZE; d+=DATA_STEP) {
cudaMemcpyAssync(d_data, h_data + d, DATA_STEP, cudaMemcpyHostToDevice, streams[sid]);
kernel<<<gridDim, blockDim, smSize streams[sid]>>>(d_data, DATA_STEP);
sid = ++sid % S_N;
}
for (int i = 0; i < S_N; i++) {
cudaStreamSynchronize(streams[i]);
cudaStreamDestroy(streams[i]);
}
但它似乎比版本慢一点点与等待忙主机线程。我认为这是因为,现在我静态分配流上的工作,所以当一个流完成工作时,它将闲置,直到每个流完成工作。以前的版本将工作动态分配到第一个空闲流,所以效率更高,但主机线程正忙着等待。
我不认为上面的代码做你想做的事情。它不会**在流1开始之前等待流0完成。相反,它确保先前在流0中启动的任何启动在流0上启动更多作业之前完成(这是不必要的,因为这已经是流的工作方式了)。为了让你的代码完成你所要求的,你需要cudaThreadSynchronize(),cudaStreamSynchronize(0)或者cudaStreamSynchronize(streams [sid-1])。 – jmilloy 2011-02-24 18:34:16
是的,你是对的,我添加while-true并行运行每个流。现在在这个循环中,我正在检查哪个流完成执行新流。 – kokosing 2011-02-25 08:38:48
不可以。你做的编辑不会做你说他们做的事,你也不了解流是如何工作的。在第一个示例中,有**没有**等待 - 您的cudaStreamQueries **总是**返回true,因为您在*之前将* c *发送任何东西之前调用cudaStreamQuery(x)*。在新示例中,您在同步之前调用内核。速度较慢,因为同步必须等待memcpy /内核完成。 – jmilloy 2011-02-25 12:25:27