在C ++中将FP32转换为Bfloat16

时间:2019-03-20 03:41:52

标签: c++ floating-point

如何在C ++中将float(1bit sign,8bit exp,23bit尾数)转换为Bfloat16(1bit sign,8bit exp,7bit尾数)?

3 个答案:

答案 0 :(得分:1)

answer by Botje所示,由于位模式相同,因此复制float值的上半部分就足够了。该答案中的处理方式违反了C ++中有关严格别名的规则。解决方法是使用memcpy复制位。

static inline tensorflow::bfloat16 FloatToBFloat16(float float_val)
{
    tensorflow::bfloat16 retval;
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
    memcpy(&retval, &float_val, sizeof retval);
#else
    memcpy(&retval, reinterpret_cast<char *>(&float_val) + sizeof float_val - sizeof retval, sizeof retval);
#endif
    return retval;
}

如果有必要舍入而不是舍弃结果,可以乘以一个魔术值,将其中一些低位压入高位。

float_val *= 1.001957f;

答案 1 :(得分:1)

由于某种原因,

memcpy在小端序情况下不会为我编译。这是我的解决方案。 我在这里将其作为结构,以便可以轻松访问数据并运行不同范围的值以确认其正常工作。

struct bfloat16{
   unsigned short int data;
   public:
   bfloat16(){
      data = 0;
   }
   //cast to float
   operator float(){
      unsigned int proc = data<<16;
      return *reinterpret_cast<float*>(&proc);
   }
   //cast to bfloat16
   bfloat16& operator =(float float_val){
      data = (*reinterpret_cast<unsigned int *>(&float_val))>>16;
      return *this;
   }
};

//an example that enumerates all the possible values between 1.0f and 300.0f
using namespace std;

int main(){
   bfloat16 x;
   for(x = 1.0f; x < 300.0f; x.data++){
      cout<<x.data<<" "<<x<<endl;
   }
   
   return 0;
}

答案 2 :(得分:0)

来自Tensorflow implementation

static inline tensorflow::bfloat16 FloatToBFloat16(float float_val) {
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
    return *reinterpret_cast<tensorflow::bfloat16*>(
        reinterpret_cast<uint16_t*>(&float_val));
#else
    return *reinterpret_cast<tensorflow::bfloat16*>(
        &(reinterpret_cast<uint16_t*>(&float_val)[1]));
#endif
}