在c++中使用不同的IEEE浮点舍入模式
Working with different IEEE floating-point rounding modes in C++
我真倒霉,我必须确保在GPU和CPU上获得相同的浮点结果。好的,我知道IEEE已经照顾了我,并提供了一个很好的标准,坚持几个四舍五入选项;CUDA部分被整理出来(有不同舍入模式的内在特性),所以这只是动机。
但是在主机端c++代码中-我如何在特定的舍入模式下执行浮点运算(我的意思是在特定的语句中,而不是在整个翻译单元中)?是否有包装器函数在底层使用汇编?是否有一组具有不同舍入模式的浮点数代理的类?
我也问同样的问题关于翻译单位水平。如何使编译器(gcc/clang/MSVC)在编译翻译单元时默认为某种舍入模式?
在@AndreasPapadopoulos的引导下,看起来有一种官方的方式来改变舍入模式:
int fesetround(int round)
int fegetround()
但是有几个注意事项:
- 这是c++ 11,而不是c++ 98(尽管在实践中你可能只使用你的系统的
<fenv.h>
是C99)。 - 需要通过
#pragma
的 与编译器通信。
我不确定这在实践中使用得有多广泛(以及是否有更常用的更好的抽象)。
处理这个问题的一个简单方法是引入一个类,它在初始化时设置舍入模式,并在超出作用域时将其重置为前一个模式,如下所示:
#include <cfenv>
//Simple class to enable directed rounding in floating-point math and to reset
//the rounding mode afterwards, when it goes out of scope
struct SetRoundingMode {
const int old_rounding_mode;
SetRoundingMode(const int mode) : old_rounding_mode(fegetround()) {
if(std::fesetround(mode)!=0){
throw std::runtime_error("Failed to set directed rounding mode!");
}
}
~SetRoundingMode(){
// More recent versions of C++ don't like exceptions in the destructor
// so you may need a different way of handling issues here.
if(std::fesetround(old_rounding_mode)!=0){
throw std::runtime_error("Failed to reset rounding mode to original value!");
}
}
static std::string get_rounding_mode_string() {
switch (fegetround()) {
case FE_DOWNWARD: return "downward";
case FE_TONEAREST: return "to-nearest";
case FE_TOWARDZERO: return "toward-zero";
case FE_UPWARD: return "upward";
default: return "unknown";
}
}
};
你可以这样使用
void foo(){
const auto srm = SetRoundingMode(FE_UPWARD);
}
请注意,所有舍入模式都在类中列出。
相关文章:
- C++将浮点指针值舍入为小数位数
- Boost::posix_time::ptime舍入到给定的分钟数
- 浮点定向舍入和优化
- 为什么输出精度没有正确舍入?
- 使用设置精度时如何阻止数字向上舍入?
- 如何在使用 MPFR 时在提升多精度中设置舍入模式
- OpenCV 细分一致的 Rect2f 到 Rect2i 舍入
- C++ 中的舍入函数
- 舍入 QDecDouble 值,精度最多为两个字符
- 将大 int 转换为浮点数,而不舍入 c++
- 舍入错误检测
- 根据浮点符号对浮点进行舍入的最简单方法是什么
- 将整数舍入到另一个整数的最接近的倍数
- Sizeof 舍入到对齐方式,但编译器仍将对象放在剩余的字节中
- 避免将 Int 转换为双重类型转换舍入
- 浮点数学运算后舍入不一致
- 浮动到绳子而无需舍入
- C++长双精度格式而不舍入
- 是否可以为 AVR 编写一个 constexpr 舍入函数?
- 在c++中使用不同的IEEE浮点舍入模式