[英]How come multiplication is as fast as addition for C++ double type values?
#include<vector>
#include<iostream>
#include<random>
#include<chrono>
int main()
{
int i;
std::mt19937 rng(std::chrono::system_clock::now().time_since_epoch().count());
std::uniform_real_distribution<double> dist(0.5, 1);
std::vector<double> q;
int N = 100000000;
for (i = 0; i < N; ++i) q.emplace_back(dist(rng));
double sum = 0;
auto start = std::chrono::steady_clock::now();
for (i = 1; i < 100000000; ++i) {
sum += q[i] + q[i - 1]; // change + to - or * or /, it takes same time.
}
auto end = std::chrono::steady_clock::now();
std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << std::endl;
std::cout << sum << std::endl;
}
加法和減法應該是簡單的過程,可能是一些移位和按位運算,其成本與精度成正比。
而乘法和除法自然是更復雜的過程。 說乘法,它的數量級要慢一些似乎很自然(如果加法需要 O(n),則類似於 O(n^2),因為乘法可以分解為移位值的加法)對於除法,它應該更難.
然而,對於使用雙精度類型值的所有 4 個算術運算,此代碼需要大約 110 毫秒,並進行了優化。 這怎么可能? 這里發生了什么神奇的事情,讓 C++ 能夠像加法一樣快地處理乘法,或者像乘法一樣緩慢地處理加法?
ps 對於 integer,它需要〜兩倍的時間,僅用於除法。
在某些處理器上,浮點乘法與加法一樣快,因為:
盡管如此,您可能會看到加法和乘法時間之間的差異。 當前的處理器設計相當復雜,處理器通常具有多個單元來執行各種浮點運算。 一個處理器可以有更多的單位來做加法而不是做乘法,所以它可以在單位時間內做比乘法更多的加法。
但是,請注意您使用的表達式:
sum += q[i] + q[i - 1];
這導致sum
串行依賴於它的先前值。 處理器可以將q[i]
與q[i-1]
相加,而無需等待先前的加法,但是,要與sum
,它必須等待先前的與sum
完成。 這意味着,如果一個處理器有兩個加法單元,它可以同時處理q[i] + q[i-1]
和之前的sum
運算。 但是,如果它有更多的附加單元,它不能更快地 go。 它可以使用額外的單元來為i
的不同值做更多的q[i] + q[i - 1]
加法,但是sum
的每個加法都必須等待前一個加法。 因此,對於兩個或更多加法單元,此計算取決於加法的延遲,即進行一次加法所需的時間。 (這與加法的吞吐量相反,如果沒有串行依賴,處理器在單位時間內可以進行多少次加法。)
如果您使用不同的計算,例如sum += q[i];
或sum0 += q[i]; sum1 += q[i+1]; sum2 += q[i+2]; sum3 += q[i+3];
sum0 += q[i]; sum1 += q[i+1]; sum2 += q[i+2]; sum3 += q[i+3];
,然后您可以看到不同的加法和乘法時間,具體取決於處理器有多少個加法單元和多少個乘法單元。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.