Memory 当所有内核都需要全局内存访问时,如何CUDA化代码
没有CUDA,我的代码只是两个for循环,用于计算系统中所有坐标对之间的距离,并将这些距离排序到容器中 我的CUDA版本的问题在于,显然线程不能同时写入相同的全局内存位置(竞争条件?)。我最终为每个存储箱获取的值不正确,因为只有一个线程最终写入每个存储箱Memory 当所有内核都需要全局内存访问时,如何CUDA化代码,memory,parallel-processing,cuda,Memory,Parallel Processing,Cuda,没有CUDA,我的代码只是两个for循环,用于计算系统中所有坐标对之间的距离,并将这些距离排序到容器中 我的CUDA版本的问题在于,显然线程不能同时写入相同的全局内存位置(竞争条件?)。我最终为每个存储箱获取的值不正确,因为只有一个线程最终写入每个存储箱 __global__ void computePcf( double const * const atoms, double * bins, int numParticles, d
__global__ void computePcf(
double const * const atoms,
double * bins,
int numParticles,
double dr) {
int i = blockDim.x * blockIdx.x + threadIdx.x;
if (i < numParticles - 1) {
for (int j = i + 1; j < numParticles; j++) {
double r = distance(&atoms[3*i + 0], &atoms[3*j + 0]);
int binNumber = floor(r/dr);
// Problem line right here.
// This memory address is modified by multiple threads
bins[binNumber] += 2.0;
}
}
}
全局无效计算cf(
双常数*常数原子,
双*箱,
int numParticles,
双dr){
int i=blockDim.x*blockIdx.x+threadIdx.x;
如果(i
所以。。。我不知道该怎么办。我一直在谷歌上搜索和阅读有关共享内存的内容,但问题是,在我进行距离计算之前,我不知道要访问哪个内存区域
我知道这是可能的,因为一个叫做VMD的程序使用GPU来加速这个计算。任何帮助(甚至想法)都将不胜感激。我不需要优化,只需要功能。有多少个
箱子[]
?
是否有某种原因导致箱子[]
需要为双箱类型?从你的代码中看不明显。您所拥有的基本上是一个操作,您可能希望了解快速并行直方图技术。可能有兴趣
有几种可能的途径来考虑你的代码:
看看是否有办法重新构造算法,以使给定的一组线程(或bin计算)不会相互重叠的方式安排计算。这也许可以根据排序距离来实现
使用此选项可以解决您的问题,但在执行时间方面可能会付出高昂的代价(但因为它非常简单,您可能想尝试一下。)代替此选项:
bins[binNumber] += 2.0;
大概是这样的:
int * bins,
...
atomicAdd(bins+binNumber, 2);
如果bin
的类型为double
,您仍然可以这样做,这只是稍微复杂一点。有关如何在double
上执行atomicAdd
的示例,请参阅
如果存储箱的数量很小(可能只有几千个或更少),则可以创建几个由多个线程块更新的存储箱集,然后在处理序列结束时使用缩减操作(逐个元素将存储箱集相加)。在这种情况下,您可能需要考虑使用较少数量的线程或线程块,每个线程处理多个元素,通过在内核代码中添加一个循环,从而在每个粒子处理完成后,通过添加<代码> GRIDIMD.x*BuffDim.x/Cuff>到<代码> i>代码>变量,循环跳到下一个粒子,重复这个过程。由于每个线程或threadblock都有自己的容器本地副本,所以它可以在不影响其他线程访问的情况下执行此操作
例如,假设我只需要1000个int类型的箱子,我可以创建1000组箱子,这只需要大约4兆字节。然后我可以给1000个线程中的每个线程它自己的bin集,然后1000个线程中的每个线程都有它自己的bin集要更新,并且不需要原子,因为它不会干扰任何其他线程。通过让每个线程在多个粒子之间循环,我仍然可以通过这种方式有效地保持机器忙碌。当所有的粒子装箱完成后,我必须将我的1000个箱子集添加到一起,可能需要一个单独的内核调用