[英]Are C/C++ library functions and operators the most optimal ones?
因此,在分而治之課程中,我們被教導:
現在,給定2個正整數a和b是operator::*
比karatsuba(a,b)
快karatsuba(a,b)
或者pow(a,b)
比
int fast_expo(int Base, int exp)
{
if (exp == 0) {
return 1;
}
if (exp == 1) {
return Base
}
if (exp % 2 == 0) {
return fast_expo(Base, exp / 2) * fast_expo(Base, exp / 2);
}
else {
return base * fast_expo(Base, exp / 2) * fast_expo(Base, exp / 2);
}
}
我問這個問題是因為我想知道它們是否只是出於教學目的,或者它們是否已經以C / C ++語言實現
唐津乘法是用於大整數的一種特殊技術。 它不能與將基本類型(例如int
和double
操作數相乘的內置C ++ *
運算符相提並論。
要使用唐津(Karatsuba),您必須使用至少由8個單詞組成的多精度整數。 (如果是64位字,則為512位)。 根據對該問題的公認答案,唐津羽場變得有利的收支平衡點在8到24個機器單詞之間。
與一對double
類型的浮點操作數一起使用的pow
函數不能與您的fast_expo
,后者與int
類型的操作數一起使用。 它們是具有不同要求的不同功能。 使用pow
,您可以計算5的立方根: pow(5, 1/3.0)
。 如果那是您想要計算的,那么無論多快, fast_expo
都沒有用。
不能保證編譯器或C庫的pow
絕對是您的計算機對兩個雙精度浮點數求冪的最快方法。
浮點數的優化聲明可能很棘手,因為經常會發生“相同”函數的多個實現在最后一位沒有給出完全相同的結果的情況。 您可能可以編寫一個快速的my_pow
,該精度僅好於五個精度的十進制數字,並且在您的應用程序中,近似值可能my_pow
。 你打敗圖書館了嗎? 幾乎不; 您的快速功能不符合將其替換為庫中pow
資格的要求。
operator::*
和其他標准運算符通常映射到硬件提供的原語。 萬一此類原語不存在(例如,IA32上的64位long long
),編譯器會對其進行仿真,但會降低性能(gcc在libgcc
中libgcc
)。
與std::pow
相同。 它是標准庫的一部分,沒有強制以某種方式實現。 GNU libc將pow(a,b)
為exp(log(a) * b)
。 exp
和log
相當長,在編寫時要考慮IEEE754浮點以實現最佳性能。
至於你的建議:
小號唐津乘法不值得。 處理器提供的乘法器指令已經針對所使用的標准數據類型的速度和功耗進行了優化。 有了更大的數字,即寄存器容量的10到20倍, 它就會開始獲得回報 :
在GNU MP Bignum庫中 ,過去的默認
KARATSUBA_THRESHOLD
用於非模數乘法(即,當n>=32w
且通常w=32
時使用Karatsuba); 模冪的最佳閾值往往要高得多。 在現代CPU上,軟件中的Karatsuba對於諸如PDS 256上的ECDSA之類的東西(n=256
,w=32
或w=64
)來說往往是無益的,但是可以想象得到,對於RSA中使用的更寬的模數有用。
這是一個包含乘法算法 ,GNU MP使用及其各自閾值的列表。
快速取冪不適用於非整數冪,因此它實際上不能與pow
相提並論。
檢查操作速度的一種好方法是對其進行測量。 如果您進行了十億次左右的計算,然后查看執行了多少時間,那么答案就在那里。
要注意的一件事。 我導致相信%相當昂貴。 有一種更快的方法來檢查某物是否可被2整除:
check_div_two(int number)
{
return ((number>>1) & 0x01);
}
這樣,您只是做了一點移動,並與蒙版進行了比較。 我認為這是一個便宜些的操作。
內置類型的*
運算符幾乎肯定會實現為單個CPU乘法指令。 因此,最終這是一個硬件問題,而不是語言問題。 在沒有直接硬件支持的情況下, 可能會生成更長的代碼序列(可能是函數調用)。
可以肯定地說,芯片制造商(英特爾,AMD等)花費了大量精力使算術運算盡可能高效。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.