2016-02-20 66 views
0

我擔心我的一個cuda內核中潛在的競爭條件。我正在研究Barnes Hunt Tree算法的N-Body模擬器。此內核的目的是計算樹的每個分支的總質量和質量中心。我想在容器數組上以相反順序「迭代」,因爲那些分配的最後一個最不可能依賴於其他子容器,數組中的第一個容器也可能依賴於後來的容器。執行期間可以中斷執行塊嗎?

我正在使用原子計數器來跟蹤哪些塊首先啓動,並且第一個塊處理前幾個容器等等。我擔心的是,一個區塊的執行可能暫時中止,直到其他區塊完成或類似的事情?這是一個問題,因爲說第一個街區開始,然後出於任何原因而屈服於其他街區。在這種情況下,如果其他依賴於第一個塊執行的計算,他們將無限循環。

__global__ void compute_mass_centers_kernel() 
{ 
    int blockNum = atomicAdd(&dev::block_number, 1); 
    int cindex = dev::ncontainers - blockNum * blockDim.x - 1 - threadIdx.x; 
    if(cindex < 0) 
     return; 

    Container& c = dev::containers[cindex]; 
    int missing_ptrs[8]; 
    int missing = 0; 

    float total_mass = 0.0f; 
    double3 com = {0}; 
    for(int i = 0; i < 8; i++) 
    { 
     if(c[i] > 1) 
     { 
      Object& o = objat(c[i]); 
      total_mass += o.m; 
      com.x += (double)o.p.x * o.m; 
      com.y += (double)o.p.y * o.m; 
      com.z += (double)o.p.z * o.m; 
     } 
     else if(c[i] < 1) 
     { 
      missing_ptrs[missing++] = c[i]; 
     } 
    } 

    while(missing) 
    { 
     for(int i = 0; i < missing; i++) 
     { 
      Container& c2 = ctrat(missing_ptrs[i]); 
      if(c2.total_mass >= 0.0f) 
      { 
       total_mass += c2.total_mass; 
       com.x += (double)c2.center_of_mass.x * c2.total_mass; 
       com.y += (double)c2.center_of_mass.y * c2.total_mass; 
       com.z += (double)c2.center_of_mass.z * c2.total_mass; 
       missing_ptrs[i--] = missing_ptrs[--missing]; 
      } 
     } 
    } 

    c.center_of_mass.x = com.x/total_mass; 
    c.center_of_mass.y = com.y/total_mass; 
    c.center_of_mass.z = com.z/total_mass; 
    c.total_mass = total_mass; 
} 

void compute_mass_centers() 
{ 
    int threads, blocks; 
    cudaOccupancyMaxPotentialBlockSize(&blocks, &threads, compute_mass_centers_kernel, 0, 0); 
    cucheck(); 

    int ncontainers; 
    cudaMemcpyFromSymbol(&ncontainers, dev::ncontainers, sizeof(int), 0, cudaMemcpyDeviceToHost); 
    cucheck(); 

    blocks = (ncontainers + (threads - 1))/threads; 

    cudaMemcpyToSymbol(dev::block_number, &ZERO, sizeof(int), 0, cudaMemcpyHostToDevice); 
    cucheck(); 

    compute_mass_centers_kernel<<< blocks, threads >>>(); 
    cucheck(); 
} 
+2

我真的不是100%肯定它是什麼,你真的想知道這裏,因爲它似乎連接到代碼甩了你在內,但沒有塊調度,執行,或在CUDA運行時模型退休秩序的保證。任何依賴預定執行順序的代碼都依賴於未定義的行爲。 – talonmies

回答

1

沒有像CUDA塊間同步那樣的東西。儘管如此,人們已經做了研究,例如:Shucai Xiao and Wu-chun Feng塊間GPU通信 通過快速的柵欄同步

你的情況,人們可以簡單地做或者幾個內核,每一個塊調用或者如果你是冒險精神在全局內存中自制(緩慢)阻塞原子操作來同步。

對於您的潛在問題,最好的解決方案可能是用cuda-memcheck檢查您的代碼。

+0

總是值得指出的是,在符合CUDA編程模型的同時,在塊之間沒有任何依賴關係。代碼現在可以工作,但沒有保證它明天會起作用。 – Jez

+0

爲什麼我得到一個倒票?有趣的是,我想我已經很清楚了,在CUDA中沒有像句子一中的塊間同步那樣的東西。第2段是啓動多個內核而不是一個的調試可能性,第3段是他正在尋找的實際工具,但似乎並不知道它存在。 – Ax3l