gpt4 book ai didi

gpu - OpenACC 红黑 Gauss-Seidel 比 CPU 慢

转载 作者:行者123 更新时间:2023-12-01 04:01:58 26 4
gpt4 key购买 nike

我为拉普拉斯方程(一个简单的加热板问题)在我的红黑 Gauss-Seidel 求解器中添加了 OpenACC 指令,但是 GPU 加速的代码并不比 CPU 快,即使对于大问题也是如此。

我还编写了一个 CUDA 版本,它比两者都快得多(对于 512x512,与 CPU 和 OpenACC 的 25 秒相比,大约为 2 秒)。

谁能想到造成这种差异的原因?我意识到 CUDA 提供了最大的潜在速度,但 OpenACC 应该为更大的问题提供比 CPU 更好的东西(例如用于演示 here 的同类问题的 Jacobi 求解器)。

这是相关代码(完整的工作源是 here ):

#pragma acc data copyin(aP[0:size], aW[0:size], aE[0:size], aS[0:size], aN[0:size], b[0:size]) copy(temp_red[0:size_temp], temp_black[0:size_temp])
// red-black Gauss-Seidel with SOR iteration loop
for (iter = 1; iter <= it_max; ++iter) {
Real norm_L2 = 0.0;

// update red cells
#pragma omp parallel for shared(aP, aW, aE, aS, aN, temp_black, temp_red) \
reduction(+:norm_L2)
#pragma acc kernels present(aP[0:size], aW[0:size], aE[0:size], aS[0:size], aN[0:size], b[0:size], temp_red[0:size_temp], temp_black[0:size_temp])
#pragma acc loop independent gang vector(4)
for (int col = 1; col < NUM + 1; ++col) {
#pragma acc loop independent gang vector(64)
for (int row = 1; row < (NUM / 2) + 1; ++row) {

int ind_red = col * ((NUM / 2) + 2) + row; // local (red) index
int ind = 2 * row - (col % 2) - 1 + NUM * (col - 1); // global index

#pragma acc cache(aP[ind], b[ind], aW[ind], aE[ind], aS[ind], aN[ind])

Real res = b[ind] + (aW[ind] * temp_black[row + (col - 1) * ((NUM / 2) + 2)]
+ aE[ind] * temp_black[row + (col + 1) * ((NUM / 2) + 2)]
+ aS[ind] * temp_black[row - (col % 2) + col * ((NUM / 2) + 2)]
+ aN[ind] * temp_black[row + ((col + 1) % 2) + col * ((NUM / 2) + 2)]);

Real temp_old = temp_red[ind_red];
temp_red[ind_red] = temp_old * (1.0 - omega) + omega * (res / aP[ind]);

// calculate residual
res = temp_red[ind_red] - temp_old;
norm_L2 += (res * res);

} // end for row
} // end for col

// update black cells
#pragma omp parallel for shared(aP, aW, aE, aS, aN, temp_black, temp_red) \
reduction(+:norm_L2)
#pragma acc kernels present(aP[0:size], aW[0:size], aE[0:size], aS[0:size], aN[0:size], b[0:size], temp_red[0:size_temp], temp_black[0:size_temp])
#pragma acc loop independent gang vector(4)
for (int col = 1; col < NUM + 1; ++col) {
#pragma acc loop independent gang vector(64)
for (int row = 1; row < (NUM / 2) + 1; ++row) {

int ind_black = col * ((NUM / 2) + 2) + row; // local (black) index
int ind = 2 * row - ((col + 1) % 2) - 1 + NUM * (col - 1); // global index

#pragma acc cache(aP[ind], b[ind], aW[ind], aE[ind], aS[ind], aN[ind])

Real res = b[ind] + (aW[ind] * temp_red[row + (col - 1) * ((NUM / 2) + 2)]
+ aE[ind] * temp_red[row + (col + 1) * ((NUM / 2) + 2)]
+ aS[ind] * temp_red[row - ((col + 1) % 2) + col * ((NUM / 2) + 2)]
+ aN[ind] * temp_red[row + (col % 2) + col * ((NUM / 2) + 2)]);

Real temp_old = temp_black[ind_black];
temp_black[ind_black] = temp_old * (1.0 - omega) + omega * (res / aP[ind]);

// calculate residual
res = temp_black[ind_black] - temp_old;
norm_L2 += (res * res);

} // end for row
} // end for col

// calculate residual
norm_L2 = sqrt(norm_L2 / ((Real)size));

if(iter % 100 == 0) printf("%5d, %0.6f\n", iter, norm_L2);

// if tolerance has been reached, end SOR iterations
if (norm_L2 < tol) {
break;
}
}

最佳答案

好吧,我找到了一个半解决方案,可以显着减少较小问题的时间。

如果我插入行:

acc_init(acc_device_nvidia);
acc_set_device_num(0, acc_device_nvidia);

在我开始我的计时器之前,为了激活和设置 GPU,512x512 问题的时间下降到 9.8 秒,1024x1024 下降到 42。增加问题的大小进一步表明,与在四个 CPU 内核上运行相比,OpenACC 的速度有多快。

通过这一变化,OpenACC 代码比 CUDA 代码慢 2 倍,随着问题规模越来越大,差距越来越接近慢一点(~1.2)。

关于gpu - OpenACC 红黑 Gauss-Seidel 比 CPU 慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12979870/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com