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