【问题标题】:Working with different IEEE floating-point rounding modes in C++在 C++ 中使用不同的 IEEE 浮点舍入模式
【发布时间】:2017-01-05 06:37:24
【问题描述】:

不幸的是,我必须确保在 GPU 和 CPU 上获得相同的浮点结果。好的,我知道 IEEE 已经照顾了我,并提供了一个很好的标准来遵守几个舍入选项;并且 CUDA 部分被整理出来(有不同舍入模式的内在函数),所以这只是动机。

但是在主机端 C++ 代码中 - 我如何在特定舍入模式下执行浮点运算(我的意思是在特定语句中,而不是在整个翻译单元中)?是否有在引擎盖下使用组装的包装器功能?是否有一组具有不同舍入模式的浮点数代理类?

我也在问关于翻译单元级别的相同问题。编译翻译单元时如何使编译器(gcc/clang/MSVC)默认为某种舍入模式?

【问题讨论】:

标签: c++ rounding ieee-754 idioms


【解决方案1】:

在@AndreasPapadopoulos 的指导下,看起来there is an official way 更改了舍入模式:

int fesetround(int round)
int fegetround()

但有几点需要注意:

  1. 这是 C++11,而不是 C++98(尽管实际上您可能只使用系统的 <fenv.h>,即 C99。
  2. 它需要通过#pragma's 与编译器通信
  3. 此切换可能很慢。

我不确定这在实践中的使用范围有多广(以及是否有任何更好的抽象更常用)。

【讨论】:

    【解决方案2】:

    一种简单的处理方法是引入一个类,该类在其初始化时设置舍入模式,并在超出范围时将其重置为先前的模式,如下所示:

    #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);
    }
    

    请注意,所有舍入模式都列在类中。

    【讨论】:

      猜你喜欢
      • 2020-06-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-20
      • 2011-10-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多