【发布时间】:2022-01-05 07:52:25
【问题描述】:
我对@987654321@ 给出的代码应用了过滤器锁定。锁定算法参考Filter Lock Algorithm。
#include <stdio.h>
__device__
void releaseLock(int i, int* level) {
level[i] = -1;
}
__device__
bool sameOrHigher(int i, int j, int *level, int n) {
for(int k = 0; k < n; k++) {
if (k!= i && level[k] >= j) return true;
}
return false;
}
__device__
void acquireLockWithNeighbours(int i, int *level, int *victim, int n)
{
for (int j = 0; j < n; j++) {
level [i] = j;
victim [j] = i;
// wait while conflicts exist
while (sameOrHigher(i, j, level, n) && victim[j] == i);
}
}
__global__
void saxpy(int n, float a, float *x, float *y, int *level, int *victim)
{
int i = blockIdx.x*blockDim.x + threadIdx.x;
if(i >= n) return;
acquireLockWithNeighbours(i, level, victim, n);
if (i < n) y[i] = a*x[i] + y[i];
releaseLock(i, level);
}
int main(void)
{
int N = 1024;
float *x, *y, *d_x, *d_y;
x = (float*)malloc(N*sizeof(float));
y = (float*)malloc(N*sizeof(float));
cudaMalloc(&d_x, N*sizeof(float));
cudaMalloc(&d_y, N*sizeof(float));
int *l, *v, *d_l, *d_v;
l = (int*)malloc(N*sizeof(int));
v = (int*)malloc(N*sizeof(int));
cudaMalloc(&d_l, N*sizeof(int));
cudaMalloc(&d_v, N*sizeof(int));
for (int i = 0; i < N; i++) {
x[i] = 1.0f;
y[i] = 2.0f;
l[i] = -1;
v[i] = -1;
}
cudaMemcpy(d_x, x, N*sizeof(float), cudaMemcpyHostToDevice);
cudaMemcpy(d_y, y, N*sizeof(float), cudaMemcpyHostToDevice);
cudaMemcpy(d_l, l, N*sizeof(int), cudaMemcpyHostToDevice);
cudaMemcpy(d_v, v, N*sizeof(int), cudaMemcpyHostToDevice);
saxpy<<<(N+255)/256, 256>>>(N, 2.0f, d_x, d_y, d_l, d_v);
cudaMemcpy(y, d_y, N*sizeof(float), cudaMemcpyDeviceToHost);
float maxError = 0.0f;
cudaMemcpy(y, d_y, N*sizeof(float), cudaMemcpyDeviceToHost);
float maxError = 0.0f;
for (int i = 0; i < N; i++)
maxError = max(maxError, abs(y[i]-4.0f));
printf("Max error: %f\n", maxError);
}
问题是:1 给出的代码可以正常执行。但是上面的代码卡住了。
任何建议将不胜感激:
-
代码中存在的任何错误,只要删除就会使其运行。
-
还有其他方法来编码锁吗?我想模拟一个图,其中每个节点都有执行能力。我正在寻找一个锁,其中每个节点都与邻居互斥执行。每个节点都知道它的邻居;对于我可以使用的锁类型的任何建议将不胜感激。
【问题讨论】:
-
您是否确保所有参与的线程都在同时运行(每个块 256 个线程听起来不错,每个 SM 可能 1 到 4 个块,网格大小与系统上 SM 的数量, 1024/256 = 4 应该也可以)。您的内存指令可能必须是易失的,并且您必须引入内存围栏,如果不是原子和同步指令的话。这种锁定算法通常不太适合 CUDA,但您的问题规模似乎足够小。
-
是的,即使我将 N = 10 也卡住了。
-
如果你有一个早于 Volta 的 GPU 而没有独立线程调度,那么只针对一个 warp 的一个线程的 while 循环可能会阻塞一个 warp 的所有 32 个线程。请尝试使用 >> 运行(浪费 31/32 个可能的线程)。也尝试#include
auto grid = Cooperation_groups::this_grid();然后在所有内存操作之间使用 grid.sync()。