我是OpenCL编程中的绝对新手。为我的应用程序。 (分子模拟)我写了一个计算lennard-jones液体分子间电位的核心。在这个内核我需要计算所有粒子的潜在的累积值与一个:OpenCL - 计算期间的递增求和
__kernel void Molsim(__global const float* inmatrix, __global float* fi, const int c, const float r1, const float r2, const float r3, const float rc, const float epsilon, const float sigma, const float h1, const float h23)
{
float fi0;
float fi1;
float d;
unsigned int i = get_global_id(0); //number of particles (typically 2000)
if(c!=i) {
// potential before particle movement
d=sqrt(pow((0.5*h1-fabs(0.5*h1-fabs(inmatrix[c*3]-inmatrix[i*3]))),2.0)+pow((0.5*h23-fabs(0.5*h23-fabs(inmatrix[c*3+1]-inmatrix[i*3+1]))),2.0)+pow((0.5*h23-fabs(0.5*h23-fabs(inmatrix[c*3+2]-inmatrix[i*3+2]))),2.0));
if(d<rc) {
fi0=4.0*epsilon*(pow(sigma/d,12.0)-pow(sigma/d,6.0));
}
else {
fi0=0;
}
// potential after particle movement
d=sqrt(pow((0.5*h1-fabs(0.5*h1-fabs(r1-inmatrix[i*3]))),2.0)+pow((0.5*h23-fabs(0.5*h23-fabs(r2-inmatrix[i*3+1]))),2.0)+pow((0.5*h23-fabs(0.5*h23-fabs(r3-inmatrix[i*3+2]))),2.0));
if(d<rc) {
fi1=4.0*epsilon*(pow(sigma/d,12.0)-pow(sigma/d,6.0));
}
else {
fi1=0;
}
// cumulative difference of potentials
// fi[0]+=fi1-fi0; changed to full size vector
fi[get_global_id(0)]=fi1-fi0;
}
}
我的问题是在该行:FI [0] + = FI1-fi0 ;.在一元向量fi [0]中是错误的结果。 我读了一些关于减少和数的内容,但是我不知道在计算过程中如何去做。
存在我的问题的任何简单的解决方案?
通知: 我试图添加下一个内核为向量分量之和(见下面的代码),但有一个比当我使用CPU和向量更大放缓。
__kernel void Arrsum(__global const float* inmatrix, __global float* outsum, const int inmatrixsize, __local float* resultScratch)
{
// načtení indexu
int gid = get_global_id(0);
int wid = get_local_id(0);
int wsize = get_local_size(0);
int grid = get_group_id(0);
int grcount = get_num_groups(0);
int i;
int workAmount = inmatrixsize/grcount;
int startOffest = workAmount * grid + wid;
int maxOffest = workAmount * (grid + 1);
if(maxOffest > inmatrixsize){
maxOffest = inmatrixsize;
}
resultScratch[wid] = 0.0;
for(i=startOffest;i<maxOffest;i+=wsize){
resultScratch[wid] += inmatrix[i];
}
barrier(CLK_LOCAL_MEM_FENCE);
if(gid == 0){
for(i=1;i<wsize;i++){
resultScratch[0] += resultScratch[i];
}
outsum[grid] = resultScratch[0];
}
}
在这里你可能需要总和减少,否则它是原子或串行总和,这将吸引GPU的。这有点难以掌握,但实现起来相对容易(特别是如果总和的元素数是2的幂)。 – Thomas
考虑在私有内存中缓存'inmatrix [i * 3 + 0/1/2]'的值,因为您多次使用它。总之,只需使用一种简化算法。这将做的工作(已被其他人回答) – DarkZeros