2010-09-29 10 views
0

的OpenCL沒有一個全球性的屏障,將停止所有線程,所以我試圖圍繞創建工作與下面的代碼:麻煩的OpenCL從__global存儲器讀取atom_inc後

void barrier(__global uint* scratch) { 
    uint nThreads = get_global_size(0); 
    atom_inc(scratch); 
    /* this loop never terminates */ 
    while(scratch[0] < nThreads) { 
    continue; 
    } 
} 

的想法是每個線程循環,直到所有的線程增加一塊內存。

但是,從頭讀取的值[0]在線程讀取後永遠不會更改,並且會永久循環。我知道它正在增加,因爲當我將它讀回主機時它是正確的值。

全局內存是否被本地緩存?這裏發生了什麼?

+0

什麼平臺/司機/等。你在測試這個嗎? – runexe 2010-09-30 13:28:10

+0

你爲什麼要這樣做?跨工作組同步無法正常工作,因爲它們可能不會同時運行。即使這會起作用:至少對gpus來說(opencl for cpu只是沒有意義......)它會變得非常慢,因爲它必須將所有訪問序列化爲全局內存。所以,即使你只使用10000個線程(這將在中高端gpus上完全併發執行),並且原子操作在片上(僅限於費米),這樣的屏障仍然會花費超過1000000個週期(每個線程有幾個週期的讀取和寫入延遲,一次一個線程) – Grizzly 2010-10-01 03:30:54

+0

在opencl中使用全局同步的標準方式是啓動一個新的內核,對於合理的線程數應該快得多(我現在不確定nvidia,但是amd會把225μs當作kernellauch latency,而像這樣的全球障礙則需要幾個ms – Grizzly 2010-10-01 03:34:44

回答

0

發現問題:工作組的執行順序是實現定義的。這意味着某些線程可能在其他人完成後僅啓動

在我給出的代碼中,首先啓動的工作組將永遠循環等待其他人打開'屏障'。而稍後開始的工作組將不會啓動,因爲他們正在等待第一批工作的完成。

如果實現(我在Radeon 5750上,使用Stream SDK 2.2)同時執行所有工作組,那麼它可能不是問題。但是我的設置並非如此。