我正在使用CUDA并行化的C转换最初编写的C代码。 还是一个新手,我将代码的大部分内容转换为CUDA,但我的一些内核没有正确地完成工作。
这是我的内核:
__global__ void kernel(long int *neighbour, double *f, double *r, double *b, double *fn, double *rn, double *bn, int nfluidsite){
int ns = blockDim.x * blockIdx.x + threadIdx.x;
if(ns<nfluidsite)
{
double tempr = r[ns];
double tempb = b[ns];
rn[ns]=tempr;
bn[ns]=tempb;
for(int q=1;q<Q;++q)
{
double confr=r[q*NSITE+ns];
double confb=b[q*NSITE+ns];
__syncthreads();
int ns1=neighbour[q*NTOTAL+ns];
__syncthreads();
rn[q*NSITE+ns1]=confr;
bn[q*NSITE+ns1]=confb;
}
}
if(ns<NSITE)
{
for(int q=0;q<Q;++q)
{
double rqns = rn[q*NSITE+ns];
double bqns = bn[q*NSITE+ns];
__syncthreads();
r[q*NSITE+ns]=rqns;
b[q*NSITE+ns]=bqns;
f[q*NSITE+ns]=rqns+bqns;
}
}
}
所以,这段代码工作正常(尽管它根本没有优化),但我也希望在q
上并行化内部for循环。所以,我这样做了:
int ns = blockIdx.x;
int q = threadIdx.x;
我按如下方式启动了我的内核:
blocksPerGrid = NSITE;
threadsPerBlock = Q;
kernel<<<blocksPerGrid,threadsPerBlock>>>(neighbourCu, fCu, rCu, bCu, fnCu, rnCu, bnCu, nfluidsite);
它根本不起作用,CUDA没有返回任何错误,但是数组上的操作有点随机......我在完全并行化的版本中添加了__syncthreads()
命令,但它没有解决差异。
另外,我不是为什么,但如果我使用超过1024个线程,我的内核中的指令也随机运行...
好吧,我已经困惑了两个星期,如果有人看到我需要做什么,请给我一个提示!
答案 0 :(得分:0)
我认为您不需要放置它们的__syncthreads();
,您正在分配和读取线程本地(寄存器或本地内存)变量。
另一方面,您确实需要在以下代码开头的代码块之前调用__threadfence();
:
if(ns<NSITE) {
...
}
违规语句是:
rn[q*NSITE+ns1]=confr;
bn[q*NSITE+ns1]=confb;
之前和:
double rqns = rn[q*NSITE+ns];
double bqns = bn[q*NSITE+ns];
后。
由于一个线程写入某个全局内存而另一个线程从中读取,因此您需要至少将两者都置于中间:
__threadfence();
__syncthreads();
(更多信息here)。只有当rn
和bn
被同一块中的线程修改时,这才能正常工作。如果发生甚至块外的线程都可以修改它们,那还不够:在继续之前需要保证所有块都已达到该点(注意:__syncthreads()
仅保证同一块内的线程 < / em>已达到这一点 - 它是一个块本地屏障)。您有三种选择:
在这一点上将内核拆分为两个不同的内核 - 单独的内核调用是隐式同步的。我会从这开始,看看它是否有效。
如果NSITE只是一个线程块,就像看起来一样,你可以再次按照全局和here的例子:只有最后一个块才会这样做 - 其余的只会跳过。
实施全球障碍(这不是一件容易的事 - 但如果你在谷歌周围,你会找到很好的参考资料)。