我无法弄清楚这个逻辑,所以我有一个计数器SOLUTIONS
,每次我为每个线程提供一个新解决方案时,它会以原子方式递增,但在某些情况下,单个线程可以找到多个解决方案,但是在这种情况下,我希望它再次增加当前值。这个逻辑似乎很简单,由atomicAdd
实现。但问题是,我需要将该计数器用作数组的索引。
示例:
SOME_ARRAY[tid] = STUFF; // puts stuff in individual indexes because of thread id.
atomicAdd(SOLUTIONS, 1); // increments the max solutions found.
但现在单个线程找到了两个解决方案,我希望它在当前MAX解决方案之后递增。
SOME_ARRAY[SOLUTIONS+1] = STUFF;
但据我了解,如果两个或多个线程试图这样做,它将无法正常工作?我需要第二个线程在SOLUTIONS + 2而不是写相同的位置。
我怎样才能做到这一点?任何帮助表示赞赏。
编辑:我尝试实现,这仍然不起作用,因为当我printf偏移时,两个线程打印相同的数字。当我访问d_PROGRESS
数组2
时,元素始终为85
,这是一个我从未放在那里的随机数。
__device__
bool isSafe (int row, int col, int cmp_row, int cmp_col) {
if ((col - cmp_col) == 0) {return 0;}
if (abs(row - cmp_row) == abs(col - cmp_col)) {return 0;}
return 1;
}
__global__
void nqueensKernel(int row, int n, bool one, bool all, int pitch,
Solution * d_solution,
Solution * d_PROGRESS,
Solution *d_PROGRESS_OUT,
unsigned long long * NUM_THREADS,
unsigned long long * NUM_SOLUTIONS) {
int index = threadIdx.x + blockIdx.x * blockDim.x;
int isAlone = 0;
if (index == 0) {*NUM_THREADS = 0;}
__syncthreads();
if (row == 0) {
d_PROGRESS_OUT[index * n + row] = index;
atomicAdd(NUM_THREADS, 1);
}
else {
int moresolutions = 0;
for (int col = 0; col < n; col++) {
for (int k = 0; k < row; k++) {
int checkcol = d_PROGRESS[index * n + k];
isAlone = isSafe(row, col, k, checkcol);
if (!isAlone) { /*printf("Is Alone? %d\n", isAlone);*/ break; }
}
__syncthreads();
if ( isAlone ) {
moresolutions++;
if (moresolutions == 1) {
d_PROGRESS_OUT[(index * n) + row] = col;
atomicAdd(NUM_THREADS, 1);
for (int o = 0; o < row; o++) {
d_PROGRESS_OUT[(index * n) + o] = d_PROGRESS[(index * n) + o];
}
} else if (moresolutions > 1) {
int offset = atomicAdd(NUM_THREADS, 1);
d_PROGRESS_OUT[((offset+1) * n) + row] = col;
for (int m = 0; m < row; m++) { d_PROGRESS_OUT[((offset+1) * n) + m] = d_PROGRESS[(index * n) + m]; }
}
if (row == n-1) { atomicAdd(NUM_SOLUTIONS, 1); }
}
}
}
答案 0 :(得分:1)
您希望使用SOME_ARRAY
返回的值保留atomicAdd
中的存储空间,这是之前存储在变量中的旧值添加,并通过要保留的插槽数递增原子变量。例如:
int offset = atomicAdd(SOLUTIONS, number_of_solutions_found_by_this_thread);
SOME_ARRAY[offset] = stuff;
SOME_ARRAY[offset + 1] = more stuff;
...
SOME_ARRAY[offset + number_of_solutions_found_by_this_thread - 1] = also more stuff;
假设SOLUTIONS
最初为0。
atomicAdd
。结果为0,SOLUTIONS
现为4。SOLUTIONS
增加9.结果返回4
,SOLUTIONS
现在为13 这是许多并行算法中的常见模式,需要跨线程聚合可变长度结果。