標籤:
在運行程式時,我們總希望多次啟動並執行結果,是完全一致,甚至在不同的機器與不同的OS中,程式啟動並執行結果每一位都完全相同。
事實上,程式往往很難保證做到這一點。 為什麼呢? 我們先看一個簡單的例子: 當程式使用單精確度或者雙精確度的浮點數時, 浮點數有一定的精度的限制。 單精確度的浮點數,使用23位二進位表示的尾數。 雙精確度浮點數,使用52位的二進位(http://en.wikipedia.org/wiki/IEEE_754-1985)。
如果,程式中計算下面的運算式:
double d1,d2,d3,d4,d5;
d1 = 1e-63;
d2 = 1;
d3= -1;
d4 = (d1+ d2) +d3;
d5 = d1+ (d2 +d3);
printf("d4=%e\n",d4);
printf("d5=%e\n",d5);
通常,它的結果為:
d4=0.000000e+000
d5=1.000000e-063
儘管數學表達上, d4 應該有和d5 完全相同的計算結果。但是,由於浮點數的有限精度,(d1+d2),在電腦的值為1. 最終,d4,d5的結果並不完全相同。
如果程式調用Intel MKL 函數,下面的一些因素,往往會對我們的計算結果產生影響:
1> 記憶體對齊:我們的處理器往往提供了一些專門的指令,對16 byte 或 32 byte (AVX ) 對齊記憶體位址進行存取操作。 當程式運行時,對齊或不對齊輸入資料的地址,啟動並執行代碼可能有略微差別。最終,程式的計算結果,可能不是完全一致。
2> 多線程的設定: Intel MKL 函數已經是多核最佳化後的函數,程式運行多線的數目不同,帶來相應的數值精度上也會細微的誤差。
3> 針對不同處理器的最佳化代碼: Intel MKL 能夠充分利用處理器的指令集,來取得程式的最高效能。 這樣在不同的處理器上, 程式啟動並執行代碼可能並不是完全一致,從而最終的的結果,可能也略有差別。
新的MKL 11.0提供了conditional bitwise reproducible (CBWR)的特性。 在滿足一定的條件下,它能保證MKL函數有相同的結果。如果 1)輸入/輸出的資料地址按照16或 32位元組對齊 ( 選擇執行SSE指令需要16 byte 對齊,AVX1指令32 byte 對齊)2)啟動並執行線程數目相同 3)在同一可執行檔中被調用, 那麼Intel MKL函數可以在多次執行中,有相同的計算結果。
程式不同處理器上啟動並執行時候,可能運行不同的最佳化代碼。比如, 在較舊Intel® Pentium® 4 處理器上, MKL可能運行SSE2 最佳化代碼,而在支援的AXV指令的新的機器上,MKL 的函數可能運行AVX指令的最佳化代碼。 這樣,Intel MKL函數能夠根據不同處理器的特性,提供高效的最佳化代碼。但是,當這些代碼,有不完全相同的資料處理順序時,不完全一致的代碼可能產生的最有的數值結果可能也不完全一致。 在MKL 11.0 中, 提供的一些新的函數,與環境變數。能夠協助使用者來來控製取得一致的計算結果。
下面我們看一下例子:
1> 為確保在Intel 以及Intel 相容的支援SSE2 指令的處理上,有一致的計算結果, 我們可以將程式須設定固定的線程數目, 保證輸入輸出資料的地址對齊, 並調用以下的MKL 函數:
mkl_cbwr_set(MKL_CBWR_COMPATIBLE) 或設定環境變數:MKL_CBWR_BRANCH = "COMPATIBLE"
2>在支援SSE4.1 Intel 的處理器上, 為確保MKL 函數有相同的結果。我們可以將程式須設定固定的線程數目,保證輸入輸出資料的地址對齊, 並調用以下的MKL 函數:
mkl_cbwr_set(MKL_CBWR_SSE4_1) 或設定環境變數: MKL_CBWR_BRANCH = "SSE4_1"
需要說明的是, 如果我們選擇了特定CPU最佳化的代碼, 很自然,針對一些新的處理器,MKL 可能會有一些效能開銷。 比如,對於矩陣與矩陣乘法的函數(xGEMM), AVX 最佳化代碼的效能有近乎SSE2最佳化代碼的兩倍效能。在支援AVX機器上,我們指定,該函數運行SSE2的代碼,會有不少的效能損失。對於其他的一些例子,選擇特定的最佳化代碼,可能有10%-20%的效能開銷。
相關培訓材料: /en-us/articles/conditional-bitwise-reproducibility
下載與測試Intel MKL 11.0 Beta:
來源:https://software.intel.com/zh-cn/blogs/2012/05/22/intel-mkl-2
Intel MKL函數,如何得到相同的計算結果?【轉】