我正在寫一個基於CUDA的程序,需要定期從GPU轉移一組項目到主機內存之間的統一存儲。爲了使進程保持異步,我希望使用cuda的UMA在主機內存中有一個內存緩衝區和標誌(因此GPU和CPU都可以訪問它)。 GPU將確保標誌清晰,將其項目添加到緩衝區並設置標誌。 CPU等待該標誌被設置,將其從緩衝區中複製出來並清除該標誌。據我所知,這不會產生任何競爭條件,因爲它會迫使GPU和CPU輪流,總是讀寫相對的標誌。Cuda的GPU和主機
到目前爲止,我還沒有能夠得到這個工作,因爲那裏似乎是某種形式的競爭條件。我想出了也有類似的問題,一個簡單的例子:
#include <stdio.h>
__global__
void uva_counting_test(int n, int *h_i);
int main() {
int *h_i;
int n;
cudaMallocHost(&h_i, sizeof(int));
*h_i = 0;
n = 2;
uva_counting_test<<<1, 1>>>(n, h_i);
//even numbers
for(int i = 1; i <= n; ++i) {
//wait for a change to odd from gpu
while(*h_i == (2*(i - 1)));
printf("host h_i: %d\n", *h_i);
*h_i = 2*i;
}
return 0;
}
__global__
void uva_counting_test(int n, int *h_i) {
//odd numbers
for(int i = 0; i < n; ++i) {
//wait for a change to even from host
while(*h_i == (2*(i - 1) + 1));
*h_i = 2*i + 1;
}
}
對於我來說,這種情況下總是從CPU(host h_i: 1
)第一個print語句後掛起。真正不尋常的事情(這可能是一個線索)是我可以在cuda-gdb中使用它。如果我在cuda-gdb中運行它,它將像以前一樣掛起。如果我按ctrl + C,它會將我帶到內核中的while()循環行。從那裏,令人驚訝的是,我可以告訴它繼續下去,它會結束。對於n> 2,它將在每個內核之後再次凍結在內核的while()循環中,但我可以繼續使用Ctrl + C繼續前進,並繼續。
如果有一個更好的方式來完成我想要做的,這也將是有益的。
代碼中的任何內容都不保證緩存一致性。沒有某種記憶柵欄,這種方法是行不通的。而是考慮每次啓動一個內核,與統一內存訪問相比,這相當便宜。 –
您的示例代碼不起作用,因爲在內核執行期間不能保證PCI-e總線上的內存一致性。這個遊戲的基本規則是不要嘗試和設計任何類型的執行模型,這些執行模式除了GPU和主機設備之間明確的主機驅動程序級別同步以外。 – talonmies
您未使用[Unified Memory。](http://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#um-unified-memory-programming-hd)。您正在使用零拷貝主機內存。如果你只是想看看有效的計數測試,看看[這裏](http://stackoverflow.com/questions/20345702/how-can-i-check-the-progress-of-matrix-multiplication/20381924 #20381924)。除了關於您的方法的所有其他評論之外,*今天的*統一內存實現並不旨在爲主機和當前正在執行的內核提供對內存區域的同時連貫訪問。 –