Cuda 数学与 C++ 数学
Cuda math vs C++ math
我在 CPU 上使用 C++ 和在 GPU 上使用 CUDA 实现了相同的算法。在这个算法中,我必须在数值上求解一个积分,因为没有解析答案。我必须集成的函数是一个奇怪的曲线多项式,最后有一个 exp 函数。
在 C++ 中
for(int l = 0; l < 200; l++)
{
integral = integral + (a0*(1/(r_int*r_int)) + a1*(1/r_int) + a2 + a3*r_int + a4*r_int*r_int + a5*r_int*r_int*r_int)*exp(-a6*r_int)*step;
r_int = r_int + step;
}
在 CUDA 中
for(int l = 0; l < 200; l++)
{
integral = integral + (a0*(1/(r_int*r_int)) + a1*(1/r_int) + a2 + a3*r_int + a4*r_int*r_int + a5*r_int*r_int*r_int)*__expf(-a6*r_int)*step;
r_int = r_int + step;
}
输出:
CPU: dose_output=0.00165546
GPU: dose_output=0.00142779
我认为math.h的exp
函数和CUDA的__expf
函数计算的不是一回事。我试图删除 --use_fast_math 编译器标志,认为这是原因,但似乎这两个实现都相差大约 20%。
我正在使用 CUDA 来加速医学物理算法,这些差异不是很好,因为我必须证明其中一个输出比另一个输出“更真实”,这显然可能是灾难性的患者。
差异来自函数本身吗?否则,我认为它可能来自 a_i
因素的 memcopy 或我获取它们的方式。
编辑:“完成”代码
float a0 = 5.9991e-04;
float a1 = -1.4694e-02;
float a2 = 1.1588;
float a3 = 4.5675e-01;
float a4 = -3.8617e-03;
float a5 = 3.2066e-03;
float a6 = 4.7050e-01;
float integral = 0.0;
float r_int = 5.0;
float step = 0.1/200;
for(int l = 0; l < 200; l++)
{
integral = integral + (a0*(1/(r_int*r_int)) + a1*(1/r_int) + a2 + a3*r_int + a4*r_int*r_int + a5*r_int*r_int*r_int)*exp(-a6*r_int)*step;
r_int = r_int + step;
}
cout << "Integral=" << integral << endl;
我建议在 gpu 和 cpu 上 运行 这部分。
来自 Carleton's seed database
的值
您正在使用 CUDA API 中不太准确的 exp() 实现。
基本上您可以在设备上使用三个版本的 exp() :
- exp(),越准确越好
- expf(),即单精度"equivalent"
- __expf(),这是前一个的内在版本,而且不太准确
您可以在 CUDA 文档的 Mathematical Functions Appendix 中阅读有关数学函数的不同实现的更多信息,包括双精度、单精度和内部版本:
D.2. Intrinsic Functions
The functions from this section can only be used in device code.
Among these functions are the less accurate, but faster versions of
some of the functions of Standard Functions .They have the same name
prefixed with __ (such as __sinf(x)). They are faster as they map to
fewer native instructions.
在同一页中,您会看到您删除的编译器选项只是阻止每个函数被其固有版本替换。当您明确使用 exp() 的固有版本时,删除此标志对您没有任何改变:
The compiler has an option (-use_fast_math) that forces each function
in Table 8 to compile to its intrinsic counterpart.
我在 CPU 上使用 C++ 和在 GPU 上使用 CUDA 实现了相同的算法。在这个算法中,我必须在数值上求解一个积分,因为没有解析答案。我必须集成的函数是一个奇怪的曲线多项式,最后有一个 exp 函数。
在 C++ 中
for(int l = 0; l < 200; l++)
{
integral = integral + (a0*(1/(r_int*r_int)) + a1*(1/r_int) + a2 + a3*r_int + a4*r_int*r_int + a5*r_int*r_int*r_int)*exp(-a6*r_int)*step;
r_int = r_int + step;
}
在 CUDA 中
for(int l = 0; l < 200; l++)
{
integral = integral + (a0*(1/(r_int*r_int)) + a1*(1/r_int) + a2 + a3*r_int + a4*r_int*r_int + a5*r_int*r_int*r_int)*__expf(-a6*r_int)*step;
r_int = r_int + step;
}
输出:
CPU: dose_output=0.00165546
GPU: dose_output=0.00142779
我认为math.h的exp
函数和CUDA的__expf
函数计算的不是一回事。我试图删除 --use_fast_math 编译器标志,认为这是原因,但似乎这两个实现都相差大约 20%。
我正在使用 CUDA 来加速医学物理算法,这些差异不是很好,因为我必须证明其中一个输出比另一个输出“更真实”,这显然可能是灾难性的患者。
差异来自函数本身吗?否则,我认为它可能来自 a_i
因素的 memcopy 或我获取它们的方式。
编辑:“完成”代码
float a0 = 5.9991e-04;
float a1 = -1.4694e-02;
float a2 = 1.1588;
float a3 = 4.5675e-01;
float a4 = -3.8617e-03;
float a5 = 3.2066e-03;
float a6 = 4.7050e-01;
float integral = 0.0;
float r_int = 5.0;
float step = 0.1/200;
for(int l = 0; l < 200; l++)
{
integral = integral + (a0*(1/(r_int*r_int)) + a1*(1/r_int) + a2 + a3*r_int + a4*r_int*r_int + a5*r_int*r_int*r_int)*exp(-a6*r_int)*step;
r_int = r_int + step;
}
cout << "Integral=" << integral << endl;
我建议在 gpu 和 cpu 上 运行 这部分。 来自 Carleton's seed database
的值您正在使用 CUDA API 中不太准确的 exp() 实现。
基本上您可以在设备上使用三个版本的 exp() :
- exp(),越准确越好
- expf(),即单精度"equivalent"
- __expf(),这是前一个的内在版本,而且不太准确
您可以在 CUDA 文档的 Mathematical Functions Appendix 中阅读有关数学函数的不同实现的更多信息,包括双精度、单精度和内部版本:
D.2. Intrinsic Functions
The functions from this section can only be used in device code.
Among these functions are the less accurate, but faster versions of some of the functions of Standard Functions .They have the same name prefixed with __ (such as __sinf(x)). They are faster as they map to fewer native instructions.
在同一页中,您会看到您删除的编译器选项只是阻止每个函数被其固有版本替换。当您明确使用 exp() 的固有版本时,删除此标志对您没有任何改变:
The compiler has an option (-use_fast_math) that forces each function in Table 8 to compile to its intrinsic counterpart.