1. 程式人生 >實用技巧 >其它 >資料型別和資料儲存

資料型別和資料儲存


技術標籤:程式語言資料型別資料儲存

目錄

fp16

fp32

BF16

記憶體對齊

位元組序之Little-Endian&Big-Endian

Unicode中的UTF-8, UTF-16, UTF-16LE, UTF-16BE

單精度和雙精度


fp16

是指採用2位元組(16位)進行編碼儲存的一種資料型別;

FP16包括:

1個符號位,5個指數位,10個尾數位(共16位)。

fp32

是指採用4位元組(32位)進行編碼儲存的一種資料型別;

在FP32中,每個數字都表示為:

1位表示符號(+或-),後跟8位的指數,在後面是23位的尾數(總共32位)。

BF16

BF16,有時也被稱為BFloat16或Brain Float16,是一種針對人工智慧/深度學習應用程式進行優化的新數字格式。它在谷歌Brain上獲得了廣泛的應用,包括谷歌、英特爾、Arm和許多其他公司的人工智慧加速器。

BF16背後的想法是通過降低數字的精度來減少計算能力和將張量相乘所需的能源消耗。張量是一個三維的數字矩陣;張量的乘法是計算人工智慧所需的關鍵數學運算。

現在大多數人工智慧訓練都使用FP32, 32位浮點數。雖然這意味著計算非常準確,但它需要強大的硬體和大量的電力。推理通常使用INT8, 8位整數(整數)。雖然使用諸如INT8這樣的較低精度的數字系統可以在相同的硬體上提供更高的吞吐量,從而節省電力,但是計算(預測)的結果卻不那麼準確。

BF16的目的是優化精度和預測精度之間的權衡,以增加吞吐量。

BF16數字表示為:

1個符號位+ 8個指數位+7個尾數位(總共16位)。

記憶體對齊

typedef struct {
    int a;
    double b;
    short c;
}A;

typedef struct {
    int a;
    short b;
    double c;
}B;

分別對他們求大小,sizeof(A),sizeof(B)我們所得到的結果是不同的,
sizeof(A)=24而sizeof(B)=16為什麼會產生不一樣的結果呢?
這是非常簡單的一個例子,體現了結構體的記憶體對齊規則。
在結構體中,從結構體的首地址開始,假設地址從0開始。
對結構體A來說,a佔4個位元組,佔從0~3的位元組,b是double型別佔8個位元組,佔從8~15的位元組,c佔兩個位元組,從16~17的位元組。
對結構體B來說,a佔4個位元組,從0~3,b佔兩個位元組從4~6;c佔8個位元組從8~15。
這就是記憶體對齊,對齊規則是按照成員的宣告順序,依次安排記憶體,其偏移量為成員大小的整數倍,0看做任何成員的整數倍,最後結構體的大小為最大成員的整數倍(所以這裡的A的大小是24,而不是18)。

為什麼要記憶體對齊? 1.平臺原因(移植原因):不是所有的硬體平臺都能訪問任意地址上的任意資料的;某些硬體平臺只能在某些地址處取某些特定型別的資料,否則丟擲硬體異常。 2.效能原因:資料結構(尤其是棧)應該儘可能地在自然邊界上對齊。原因在於,為了訪問未對齊的記憶體,處理器需要作兩次記憶體訪問;而對齊的記憶體訪問僅需要一次訪問。

位元組序之Little-Endian&Big-Endian

對於位元組序列的儲存格式,目前有兩大陣營,那就是Motorola的PowerPC系列CPU和Intel的x86系列CPU。PowerPC系列採用big endian方式儲存資料,而x86系列則採用little endian方式儲存資料。那麼究竟什麼是big endian,什麼又是little endian呢?

1)Little-endian:將低序位元組儲存在起始地址(低位編址)
2)Big-endian:將高序位元組儲存在起始地址(高位編址)

為什麼要注意位元組序的問題呢?你可能這麼問。當然,如果你寫的程式只在單機環境下面執行,並且不和別人的程式打交道,那麼你完全可以忽略位元組序的存在。

但是,如果你的程式要跟別人的程式產生互動呢?在這裡我想說說兩種語言。C/C++語言編寫的程式裡資料儲存順序是跟編譯平臺所在的CPU相關的,而JAVA編寫的程式則唯一採用big endian方式來儲存資料。

試想,如果你用C/C++語言在x86平臺下編寫的程式跟別人的JAVA程式互通時會產生什麼結果?就拿上面的0x12345678來說,你的程式傳遞給別人的一個數據,將指向0x12345678的指標傳給了JAVA程式,由於JAVA採取big endian方式儲存資料,很自然的它會將你的資料翻譯為0x78563412。什麼?竟然變成另外一個數字了?是的,就是這種後果。因此,在你的C程式傳給JAVA程式之前有必要進行位元組序的轉換工作。

無獨有偶,所有網路協議也都是採用big endian的方式來傳輸資料的。所以有時我們也會把big endian方式稱之為網路位元組序。當兩臺採用不同位元組序的主機通訊時,在傳送資料之前都必須經過位元組序的轉換成為網路位元組序後再進行傳輸。

目前應該little endian是主流,因為在資料型別轉換的時候(尤其是指標轉換)不用考慮地址問題。

Unicode中的UTF-8, UTF-16, UTF-16LE, UTF-16BE

  • UTF-8Eight-bit UCS Transformation Format
  • UTF-16BESixteen-bit UCS Transformation Format, big-endian byte order.其後綴是BE即big-endian,大端的意思。大端就是將高位的位元組放在低地址表示。
  • UTF-16LESixteen-bit UCS Transformation Format, little-endian byte order.其後綴是LE即little-endian,小端的意思。小端就是將高位的位元組放在高地址表示。
  • UTF-16Sixteen-bit UCS Transformation Format, byte order identified by an optional byte-order mark.沒有指定字尾,即不知道其是大小端,所以其開始的兩個位元組表示該位元組陣列是大端還是小端。即FE FF表示大端,FF FE表示小端。

單精度和雙精度

單精度是1位符號,8位指數,23位小數。

資料型別和資料儲存

雙精度是1位符號,11位指數,52位小數。

資料型別和資料儲存