我已经对我的模型进行了分析,似乎这个内核占据了我的全部运行时间的约2/3。我正在寻找优化建议。以下是代码。
__global__ void calcFlux(double* concs, double* fluxes, double* dt)
{
int idx = blockIdx.x * blockDim.x + threadIdx.x;
fluxes[idx]=knowles_flux(idx, concs);
//fluxes[idx]=flux(idx, concs);
}
__device__ double knowles_flux(int r, double *conc)
{
double frag_term = 0;
double flux = 0;
if (r == ((maxlength)-1))
{
//Calculation type : "Max"
flux = -km*(r)*conc[r]+2*(ka)*conc[r-1]*conc[0];
}
else if (r > ((nc)-1))
{
//Calculation type : "F"
//arrSum3(conc, &frag_term, r+1, maxlength-1);
for (int s = r+1; s < (maxlength); s++)
{
frag_term += conc[s];
}
flux = -(km)*(r)*conc[r] + 2*(km)*frag_term - 2*(ka)*conc[r]*conc[0] + 2*(ka)*conc[r-1]*conc[0];
}
else if (r == ((nc)-1))
{
//Calculation type : "N"
//arrSum3(conc, &frag_term, r+1, maxlength-1);
for (int s = r+1; s < (maxlength); s++)
{
frag_term += conc[s];
}
flux = (kn)*pow(conc[0],(nc)) + 2*(km)*frag_term - 2*(ka)*conc[r]*conc[0];
}
else if (r < ((nc)-1))
{
//Calculation type : "O"
flux = 0;
}
return flux;
}
仅仅为了让您理解为什么for循环是一个问题,这个内核被启动在大约maxlength=9000元素的数组上。就我们现在的目的而言,nc在2-6的范围内。以下是这个内核如何处理输入数组(conc)的插图。针对该数组,不同组别的元素需要应用五种不同类型的计算。
Array element : 0 1 2 3 4 5 6 7 8 9 ... 8955 8956 8957 8958 8959 8960
Type of calc : M O O O O O N F F F ... F F F F F Max
我现在试图解决的潜在问题是四重 if-else 和 for 循环中的分支发散。
我处理分支发散的想法是将此内核分成四个单独的设备函数或内核,分别对待每个区域并同时启动。我不确定这比让分支发散发生要好多少,如果我没记错的话,这会导致四种计算类型以串行方式运行。
为了解决 for 循环,您会注意到已注释掉 arrSum3 函数,我基于以前编写的(可能很差)并行约简内核编写它。将其用于 for 循环可以显着增加运行时间。我感觉有一种聪明的方法可以实现我尝试使用 for 循环做的事情,但我并不那么聪明,我的指导老师已经厌倦我"浪费时间"思考它。
感谢任何帮助。
编辑
完整代码位于此处:https://stackoverflow.com/q/21170233/1218689