Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ OpenCL内核浮点除法给出了不同的结果_C++_C_Floating Point_Opencl_Gpu - Fatal编程技术网

C++ OpenCL内核浮点除法给出了不同的结果

C++ OpenCL内核浮点除法给出了不同的结果,c++,c,floating-point,opencl,gpu,C++,C,Floating Point,Opencl,Gpu,我有一个OpenCL内核用于一些计算。我发现只有一个线程使用CPU代码给出不同的结果。我使用的是vs2010 x64发布模式 通过一些示例检查OpenCL代码,我发现了一些有趣的结果。下面是内核代码中的测试示例 我在OpenCl内核中测试了3个案例,通过printf(“%.10f”,fval)检查精度 案例1: 变量为:intx,y,z 这些值是通过一些操作计算出来的。它们的值是x=12,y=16,z=16 案例2: 案例3: 但是,当我使用上述两个表达式计算fval的差异时,如果使用10296

我有一个OpenCL内核用于一些计算。我发现只有一个线程使用CPU代码给出不同的结果。我使用的是vs2010 x64发布模式

通过一些示例检查OpenCL代码,我发现了一些有趣的结果。下面是内核代码中的测试示例

我在OpenCl内核中测试了3个案例,通过
printf(“%.10f”,fval)检查精度

案例1: 变量为:
intx,y,z

这些值是通过一些操作计算出来的。它们的值是x=12,y=16,z=16

案例2: 案例3: 但是,当我使用上述两个表达式计算
fval
的差异时,如果使用
10296184.0
,结果是0

浮动fval=(10296184.0)/(浮动)(x*y*z)-(10296184.0)/(浮动)(12*16*16);//给出结果fval=0.0000000000

浮动fval=(10296184.0f)/(浮动)(x*y*z)-(10296184.0f)/(浮动)(12*16*16);//得出的结果fval=0.0001812663

谁能解释一下原因或给我一些提示吗?

一些观察:

两个
float
值相差1。因此,结果相差最小

// Float ULP in the 2's place here
//       v
0x1.a2f3ea0000000p+11 3351.622314... // OP's lower float value 
0x1.a2f3eaaaaaaabp+11 3351.622395... // higher precision quotient
0x1.a2f3ec0000000p+11 3351.622558... // OP's higher float value 
<代码>(10296184.0)/(float)(12*16*16)在编译时计算,与预期数学答案的结果更接近

float fval=(10296184.0)/(float)(x*y*z)
在运行时计算

考虑到所使用的
float
变量,代码使用
double
数学进行此除法令人惊讶。这是一个
double
常数除以
double
(这是
float
产品的推广)得到的
double
商,转换为
float
,然后保存。我希望
10296184.0f
-注意
f
-已经被使用,那么数学可以全部作为
float
s完成

C允许不同的舍入模式,由
FLT_ROUNDS
表示,这可能在编译时和运行时有所不同,并可能解释这种差异。了解fegetround()的结果(函数获取当前舍入方向)会有所帮助

OP可能采用了各种编译器优化,以牺牲精度换取速度



C没有指定数学运算的精度,但是在高质量的平台上,
*/+-sqrt()modf()
应该达到最后的ULP。我怀疑代码的数学实现很弱。

请参见?这些不准确性是我总是使用双精度浮点的原因之一(尽管它也会受到同样的影响),除非一些限制迫使我使用劣质的浮点。如果你需要更高的精度,这就是双精度浮点在GPU上的原因。它在渲染中的应用非常少。发布如何确定
3351.6226、3351.6223和0
的值<代码>printf(“%f”,…)、调试器等。关键答案由@chux给出。这是编译时划分与运行时划分的错误匹配。两者的精度都不同。您使用的是什么编译器、什么平台、什么编译器设置?fegetround()的结果是什么?来自
FLT\u EVAL\u方法的值是多少。以这些信息、下面的答案、函数和宏的结果为例,我们可能已经获得了所需的所有其他信息。更大的问题在于如何以不同的方式编写代码,以减少小ULP错误的影响。
float fval = (10296184.0) / (float)(12*16*16); // which gives result fval = 3351.6223144531

float fval = (10296184.0f) / (float)(12*16*16); // which gives result fval = 3351.6223144531
// Float ULP in the 2's place here
//       v
0x1.a2f3ea0000000p+11 3351.622314... // OP's lower float value 
0x1.a2f3eaaaaaaabp+11 3351.622395... // higher precision quotient
0x1.a2f3ec0000000p+11 3351.622558... // OP's higher float value