データ圧縮の一般的な手段と方法

0. はじめに

以前「古典文学の読解 - R-PCC (距離画像に基づく点群圧縮法)」でいくつかのアルゴリズム レベルを通じてデータ圧縮を完了できると述べましたが、実際には、より単純またはより直接的な方法は、半分の形式を使用することです。データ圧縮を完了します。

1.半分とフロート

Half は、浮動小数点数を表すために 16 ビットを使用するデータ型であり、IEEE 754 でも指定されています。このデータ型は、深層学習システムで広く使用されています。ただし、現在主流のCPUはhalf型データの計算と出力をサポートしていないため、half型とfloat型の間で変換する必要があります。

図 1 は、16 ビット浮動小数点表現の標準であり、1 つの符号ビット、5 つの指数ビット、および 10 の仮数ビットが含まれます。正常値の場合、結果は次のように表されます。
ここに画像の説明を挿入
図 2 は、1 つの符号ビット、8 つの指数ビット、および 23 の仮数ビットを含む 32 ビット浮動小数点数の標準表現です。正常値の場合、結果は次のように表されます。
ここに画像の説明を挿入
したがって、half と float の間の変換では、さまざまな部分のシフトに加えて、指数の底 (15 と 127) の違いにも注意してください。ハーフ型をフロート型に変換する主な手順は以下のとおりです。

  • 符号ビットは 16 ビット左にシフトされます。
  • 指数 (127 と 15 の差) に 112 を加算し、13 ビット左にシフトします (右詰め)。
  • 仮数部は 13 ビット左にシフトされます (左詰め)。

2. ハーフとフロートのリファレンスコード

対応する参照コードは次のとおりです。


typedef unsigned short ushort;//占用2个字节
typedef unsigned int uint;    //占用4个字节
 
uint as_uint(const float x) {
    
    
    return *(uint*)&x;
}
float as_float(const uint x) {
    
    
    return *(float*)&x;
}
 
float half_to_float(const ushort x) {
    
     // IEEE-754 16-bit floating-point format (without infinity): 1-5-10, exp-15, +-131008.0, +-6.1035156E-5, +-5.9604645E-8, 3.311 digits
    const uint e = (x&0x7C00)>>10; // exponent
    const uint m = (x&0x03FF)<<13; // mantissa
    const uint v = as_uint((float)m)>>23; // evil log2 bit hack to count leading zeros in denormalized format
    return as_float((x&0x8000)<<16 | (e!=0)*((e+112)<<23|m) | ((e==0)&(m!=0))*((v-37)<<23|((m<<(150-v))&0x007FE000))); // sign : normalized : denormalized
}
ushort float_to_half(const float x) {
    
     // IEEE-754 16-bit floating-point format (without infinity): 1-5-10, exp-15, +-131008.0, +-6.1035156E-5, +-5.9604645E-8, 3.311 digits
    const uint b = as_uint(x)+0x00001000; // round-to-nearest-even: add last bit after truncated mantissa
    const uint e = (b&0x7F800000)>>23; // exponent
    const uint m = b&0x007FFFFF; // mantissa; in line below: 0x007FF000 = 0x00800000-0x00001000 = decimal indicator flag - initial rounding
    return (b&0x80000000)>>16 | (e>112)*((((e-112)<<10)&0x7C00)|m>>13) | ((e<113)&(e>101))*((((0x007FF000+m)>>(125-e))+1)>>1) | (e>143)*0x7FFF; // sign : normalized : denormalized : saturate
}


//下面的demo中,yolov5_outputs[0].buf是void *类型的,void *类型不能++,因此先转换成ushort*类型。

    float *data0 = (float*)malloc(4 * output_attrs[0].n_elems);
    float *data1 = (float*)malloc(4 * output_attrs[1].n_elems);
    float *data2 = (float*)malloc(4 * output_attrs[2].n_elems);
    unsigned short *temp0 = (ushort*)yolov5_outputs[0].buf;
    unsigned short *temp1 = (ushort*)yolov5_outputs[1].buf;
    unsigned short *temp2 = (ushort*)yolov5_outputs[2].buf;
 
    for(int i=0; i < output_attrs[0].n_elems;i++)
    {
    
    
        data0[i] = half_to_float(temp0[i]);
    }
    for(int i=0; i < output_attrs[1].n_elems;i++)
    {
    
    
       data1[i] = half_to_float(temp1[i]);
    }
    for(int i=0; i < output_attrs[2].n_elems;i++)
    {
    
    
       data2[i] = half_to_float(temp2[i]);

3. float と uint16

シリアルポート通信でよく使われますが、シリアルポートは文字型(char)でしか通信できません
atof():文字列を倍精度浮動小数点値に変換します。
atoi(): 文字列を整数値に変換します。
浮動小数点から uint16 関数へ

…詳しくは顧岳州を参照

おすすめ

転載: blog.csdn.net/lovely_yoshino/article/details/128916637