concurrency::fast_math::tanh()在parallel_for_each(C++AMP)处返回N
concurrency::fast_math::tanh() returns NaN at the parallel_for_each (C++ AMP)
我用c++amp计算了这个值。环境:VS2015,Win8.
当运行parallel_for_each函数时,值为NaN。原因是concurrency::fast_math::tanh
功能。
当参数在parallel_for_each
:中运行时大于1000
时,concurrency::fast_math::tanh
函数返回NaN
float arr[2];
concurrency::array_view<float> arr_view(2, arr);
concurrency::extent<1> ex;
ex[0] = 1;
parallel_for_each(ex, [=](Concurrency::index<1> idx) restrict(amp){
float t = 10000000;
arr_view[0] = concurrency::fast_math::fabs(t);
arr_view[1] = concurrency::fast_math::tanh(t);
});
arr_view.synchronize();
std::cout << arr[0] << "," << arr[1] << std::endl;
输出
1e+07,nan
case2,如果未运行parallel_for_each:
float arr[2];
concurrency::array_view<float> arr_view(2, arr);
concurrency::extent<1> ex;
ex[0] = 1;
float t = 10000000;
arr_view[0] = concurrency::fast_math::fabs(t);
arr_view[1] = concurrency::fast_math::tanh(t);
arr_view.synchronize();
std::cout << arr[0] << "," << arr[1] << std::endl;
输出:
1e+07,1
这是我一直期待的结果。如果将tanh更改为tanhf,则结果相同。
为什么tanh函数返回NaN?为什么,只在运行paralle_for_each时返回NaN?请告诉我原因和问题的解决方法。
fast_math
中定义的函数将速度置于精度之上。实现和精度取决于硬件。当你不使用parallel_for_each
语法时,代码将在CPU上运行,CPU只实现一个"精确"的tanh
函数,因此给出了正确的答案。
要解决此问题,您可以调用precise_math
、下的函数
concurrency::precise_math::tanh(t);
如果这太慢,并且fast_math::tanh
的精度足够,你可以尝试类似的方法
double myTanh(double t){
return (concurrency::fast_math::fabs(t)>100) ? concurrency::precise_math::copysign(1,t) : concurrency::fast_math::tanh(t);
}
根据硬件的不同,它可能比精确版本运行得更快,也可能不会。所以你需要运行一些测试。
concurrency::fast_math
中的大多数函数都不能保证返回正确的值。其中一些(如tanh)甚至可以返回NaN值。在我的HD 6870所有数字的快速tanh超过90返回NaN
以下是解决这个问题的一些技巧。
你可以将Tanh的论点"绑定"到10
float Tanh(float val) restrict(amp)
{
if (val > 10)
return 1;
else if (val < -10)
return-1;
return Concurrency::fast_math::tanh(val);
}
这不会造成任何精度损失,因为浮点只有7位数的精度,而Tanh(10)和1之间的差是4*10-9
或者,您可以实现自己的Tanh函数,它不会有这样的限制
float Tanh(float val) restrict(amp)
{
float ax = fabs(val);
float x2 = val * val;
float z = val * (1.0f + ax + (1.05622909486427f + 0.215166815390934f * x2 * ax) * x2);
return (z / (1.02718982441289f + fabs(z)));
}
在很久以前的某个地方发现了这个tanh近似。它速度很快,而且相当精确
但是,如果您需要非常精确的tanh,您可以用concurrency::precise_math
替换concurrency::fast_math
。但这个选项有一个主要的缺点:precise_math
不能在很多GPU上运行(例如我的6870)。从这里开始。
这些功能,包括单精度功能,需要扩展的双精度支持在油门上。您可以使用accelerator::supports_double_precision数据成员,以确定可以在特定的加速器上运行这些功能。
此外,precise_math
可能比fast_math
慢10倍以上,尤其是在非专业视频卡上
如果你运行的并发代码不在parallel_for_each
块中,那么看起来你实际上并没有使用gpu。因此,tanh u评估在没有GPU特定错误的CPU上进行评估。事实上,如果你运行这个代码
float t = 0.65;
arr_view[1] = concurrency::fast_math::tanh(t);
parallel_for_each(e, [=](index<1> idx) restrict(amp)
{
arr_view[0] = concurrency::fast_math::tanh(t);
});
std::cout << arr[0] << "," << arr[1] << std::endl;
arr_view.synchronize();
std::cout << arr[0] << "," << arr[1] << std::endl;
std::cout << arr[0] - arr[1] << std::endl;//may return non-zero value, depending on gpu
您可以在同步前看到第一个tanh的结果,同时获得parallel_for_each块需要的结果。此外,对我来说,它返回的结果略有不同,但这可能取决于硬件。
- 在 C++ AMP 数组中复制数据多少次?
- C++ 中用于二维数组的 for-each 循环
- 用户输入N,找到所有a和b共素数对,其中a<;N&;b<;N
- 计算 fib(n) 的次数称为 FOR EACH n
- 是否必须在内存中"next to each other"两个相邻声明的公共字段?
- 在Linux下的C 程序中包括AMP.H LIB
- 只为NOT STATIC类的EACH对象调用一次方法
- C++AMP计算和WPF渲染图形卡的双重使用性能
- Microsoft AMP for C++ with Dr Dobbs example?
- 支持自定义 const 本机C++容器类的"for each"
- 视觉C++ AMP 以不同的维度迭代array_views
- 限制(amp)函数的默认参数
- C++ for-each 语句触发"vector iterators incompatible"断言失败:this->_Getcont() == 0
- 为什么我的矢量中的项目在 C++ 中的 for-each 循环期间不会改变?
- 为什么在构建C AMP项目期间会发现链接错误
- 我何时应该使用C AMP
- 在 C++Amp 中并行执行的几种算术运算
- 设备定位的像素数组(从 C++ AMP)到 使用 D3D / D2D 的窗口
- C++ostream:没有运算符匹配<<&应在'&'代币
- 使用C++AMP时未命中视觉GPU断点