C++ 在C+中使用不同的IEEE浮点舍入模式+;

C++ 在C+中使用不同的IEEE浮点舍入模式+;,c++,rounding,ieee-754,idioms,C++,Rounding,Ieee 754,Idioms,不幸的是,我必须确保GPU和CPU上的浮点结果相同。好的,我知道IEEE已经照顾了我,并提供了一个很好的标准来坚持几个舍入选项;CUDA部分被整理出来(不同的取整模式有内在的东西),所以这就是动机 但是在主机侧C++代码中,如何在特定的舍入模式下执行浮点运算(我是指在特定语句中,而不是在整个翻译单元中)?是否有使用机罩下装配的包装器功能?是否有一组具有不同舍入模式的浮点数代理类 我也在问同样的问题,关于翻译单位级别。编译翻译单元时,如何使编译器(gcc/clang/MSVC)默认为某个舍入模式?

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

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


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

根据@AndreasPapadopoulos的介绍,似乎要更改舍入模式:

int fesetround(int round)
int fegetround()
但有几个警告:

  • 这是C++11,而不是C++98(尽管在实践中,您可能只需要使用系统的
    ,即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";
        }
      }
    };
    

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

    @AndreasPapadopoulos,但您可能可以设置它(或者发现您无法设置并重新组合)@AndreasPapadopoulos,是的,我似乎误读了您的评论,认为根本无法设置它。