[英]glibc uses kernel functions
我試圖從glibc源代碼中了解此方法:
26 #if LIBM_SVID_COMPAT
27 /* wrapper sqrtf */
28 float
29 __sqrtf (float x)
30 {
31 if (__builtin_expect (isless (x, 0.0f), 0) && _LIB_VERSION != _IEEE_)
32 return __kernel_standard_f (x, x, 126); /* sqrt(negative) */
33
34 return __ieee754_sqrtf (x);
35 }
36 libm_alias_float (__sqrt, sqrt)
37 #endif
據我了解,如果程序無法從glibc中找到sqrt
函數的有效實現,它將從內核調用硬件函數,即特定的機器函數。 這是正確的嗎?
另外, libm_alias_float (__sqrt, sqrt)
是什么意思?
GNU C庫的數學功能在“ glibc”源代碼樹中完全實現。 他們什么都不依賴操作系統內核。 在此上下文中,“內核”一詞指的是計算內核,這是某些數學算法的核心,您可能想用手工優化的匯編語言編寫該部分。
函數__kernel_standard_f
被錯誤命名。 它包含用於處理數學函數錯誤的通用代碼。 最好將其命名為__math_domain_error
。 在這種情況下,當__sqrtf
的參數為負數時, __sqrtf
調用__kernel_standard_f
。 __kernel_standard_f
然后將把errno
為EDOM
,可能會調用SVID matherr
回調,並返回NaN。 (神秘代碼126告訴__kernel_standard_f
該函數調用它,為什么。的執行__kernel_standard_f
是sysdeps/ieee754/k_standardf.c
和sysdeps/ieee754/k_standard.c
。)
條件_LIB_VERSION != _IEEE_
與是否啟用POSIX和/或SVID數學錯誤處理有關; 現代數學算法實際上只希望在結果中查找NaN,而沒有浪費庫時間設置errno
或調用matherr
,因此有一種機制可以將后兩者關閉。
如果__sqrtf
的參數不是負數,則尾部將調用__ieee754_sqrtf
,它執行平方根的實際計算。 glibc源代碼樹中有此功能的幾種替代實現。 其僅C的通用版本在sysdeps/ieee754/flt-32/e_sqrtf.c
。 (即使按照glibc的標准,實現數學功能的文件的名稱也是神秘的。我不必費心去理解它們,我只是find sysdeps -name '*sqrtf*'
或其他名稱。)此功能還以邏輯開始檢測一個負參數(也為零,無窮大和NaN)並返回適當的值,但它不會碰到errno
。 如果您想了解用於計算平方根的數學技術,請查看此文件。
如果您自己運行上述find
命令,則會發現其他幾個名為e_sqrtf.c
文件; 這些都在以特定CPU命名的目錄中,這些CPU的浮點單元對計算平方根具有硬件支持,因此sysdeps/x86_64/fpu/e_sqrt.c
讀取
double
__ieee754_sqrt (double x)
{
double res;
asm ("sqrtsd %1, %0" : "=x" (res) : "xm" (x));
return res;
}
因為x86 sqrtsd
指令可以完成全部工作。
當為其中一個CPU進行構建時,Glibc的構建過程將選擇這些文件之一,而不是通用C版本。 這種機制很復雜,並且沒有完整記錄,但是glibc手冊的“維護”附錄 ,特別是其“源布局”和“移植”部分,對它進行了詳盡的介紹。
libm_alias_float (__sqrt, sqrt)
安排__sqrtf
也使用名稱sqrtf
,但作為弱別名 。 為了符合標准,這是必需的。 如果您需要更多詳細信息,請問一個單獨的問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.