我正在尋找一種方法來擺脫閒置代碼中的主機線程中的忙碌等待(不要複製該代碼,它只會顯示我的問題,它有很多想法基本的錯誤):擺脫異步執行期間的繁忙等待
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