着色器中实现双精度cos()的结果是NaN,但在CPU上运行良好.出了什么问题
The result of own double precision cos() implemention in a shader is NaN, but works well on the CPU. What is going wrong?
正如我所说,我想在GLSL的计算着色器中实现我自己的双精度cos()函数,因为只有一个内置的float版本。
这是我的代码:
double faculty[41];//values are calculated at the beginning of main()
double myCOS(double x)
{
double sum,tempExp,sign;
sum = 1.0;
tempExp = 1.0;
sign = -1.0;
for(int i = 1; i <= 30; i++)
{
tempExp *= x;
if(i % 2 == 0){
sum = sum + (sign * (tempExp / faculty[i]));
sign *= -1.0;
}
}
return sum;
}
这段代码的结果是,着色器上的总和是NaN,但在CPU上,算法运行良好。我也试着调试这个代码,我得到了以下信息:
- 对于所有条目,facility[i]都是正的,而不是零
- tempExp在每个步骤中都为正
- 在每个步骤中,其他变量都不是NaN
- 第一个时间和是NaN,处于i=4的阶跃
现在我的问题是:如果每个变量都是一个数字,没有任何东西被零除,特别是当算法在CPU上工作时,到底会出什么问题?
让我猜一猜:
首先,您确定问题在循环中,并且只使用以下操作:+
、*
、/
。
从这些操作生成NaN
的规则是:
- 分区
0/0
和±∞/±∞
- 乘法
0×±∞
和±∞×0
- 加法
∞ + (−∞)
、(−∞) + ∞
和等价减法
您通过声明faculty[]
已正确初始化,排除了0/0
和±∞/±∞
的可能性。
变量sign
总是1.0
或-1.0
,因此它不能通过*
操作生成NaN
。
如果tempExp
变成±∞
,则剩下的是+
操作。
所以可能tempExp
在进入函数时太高,变成了±∞
,这也会使sum
变成±∞
。在下一次迭代中,您将通过:∞ + (−∞)
触发NaN
生成操作。这是因为您将加法的一侧乘以sign
,并且在每次迭代时符号在正和负之间切换。
您正试图将cos(x)
近似为0.0
。因此,您应该使用cos()
函数的属性将输入值减少到接近0.0
的值。理想地在CCD_ 33的范围内。例如,去除2*pi
的倍数,并通过计算0.0
周围的sin(x)
等来获得[pi/4, pi/2]
中cos()
的值。
可能出现严重错误的是精度损失。CCD_ 39通常通过范围缩减来实现,随后是用于范围CCD_。测距使用cos(x+2*pi) = cos(x)
。但这种范围缩小并不完美。首先,pi
不能用有限数学精确表示。
现在,如果你尝试像cos(1<<30)
这样荒谬的东西,会发生什么?距离缩减算法很可能在x
中引入了大于2*pi
的误差,在这种情况下,结果是没有意义的。在这种情况下返回NaN
是合理的。
- 在程序运行时监视 VxWorks 中的任务 CPU 利用率
- 以编程方式在运行时检测 CPU 体系结构
- C++多线程算法创建在同一 CPU 线程上运行的多个线程
- 我的OpenCL测试的运行速度不超过CPU
- 在我的CUDA运行时间计划中,CPU和GPU可以异步计算,但不能合作地计算
- 如何在运行SDL程序时降低CPU使用率
- 着色器中实现双精度cos()的结果是NaN,但在CPU上运行良好.出了什么问题
- 使用C++将CPU专用于在1个核心上运行进程
- 在运行时查找特定线程的CPU核心
- 在具有 64 位 CPU 的 32 位 Win8 上运行 32 位 Orwell Dev-C++ - 输入指针返回不正确
- 如何控制 Microsoft C 运行时库使用的 CPU 指令
- GPU 调用后,CPU 代码运行缓慢
- 如何禁止任何应用程序的所有线程在特定的CPU内核上运行,除非我指定了线程
- 计算并行程序的运行时间和cpu时间
- 如何找出我的进程Id正在哪个物理CPU上运行
- 如何在GPU上而不是在CPU上运行qt应用程序
- openmp是否可以在同一个cpu(核心)上运行不同的线程?
- 如何在一个CPU上运行c++程序
- 检查代码是否在GPU或CPU上运行
- OpenCV CUDA运行速度比OpenCV CPU慢