我重載了算術/賦值操作符std::vector
以便能夠執行一些基本的線性代數操作。但是,在鏈接這些操作時我遇到了一些性能問題。鏈接操作符時的編譯器優化
這裏是我的main.h
內容:的main1.cpp
#include <vector>
#include <stdlib.h>
using namespace std;
typedef vector<float> vec;
inline vec& operator+=(vec& lhs, const vec& rhs) {
for (size_t i = 0; i < lhs.size(); ++i) {
lhs[i] += rhs[i];
}
return lhs;
}
inline vec operator*(float lhs, vec rhs) {
for (size_t i = 0; i < rhs.size(); ++i) {
rhs[i] *= lhs;
}
return rhs;
}
內容:
內容的main2.cpp
#include "main.h"
// gcc 4.9.2 (-O3): 0m5.965s
int main(int, char**) {
float x = rand();
vec v1(1000);
vec v2(1000);
for (size_t i = 0; i < v1.size(); ++i) {
v1[i] = rand();
v2[i] = rand();
}
for (int i = 0; i < 10000000; ++i) {
v1 += x * v2;
// same as:
//vec y = x * v2;
//v1 += y;
}
return 0;
}
:
#include "main.h"
// gcc 4.9.2 (-O3): 0m2.400s
int main(int, char**) {
// same stuff
for (int i = 0; i < 10000000; ++i) {
for (size_t j = 0; j < v1.size(); ++j) {
v1[j] += x * v2[j];
}
}
return 0;
}
第二個程序運行速度比第一快得多。我明白爲什麼會出現這種情況:第一個程序不是隻有一個循環,而是兩個循環,它分配一個臨時向量。
但這是我期望編譯器看到和優化的那種東西。或者我做錯了什麼?
我不記得有線性代數庫(如犰狳)有這個問題。他們如何解決這個問題?這是否涉及一些複雜的模板編程,還是有一些簡單的方法來幫助編譯器優化它?
Armadillo大量使用表達式模板。 – 101010
我的測量數據是1和0.85 –
表達式模板幾乎可以肯定地解釋這種差異。 GMP使用類似的方法來減少不必要的工作;操作符返回描述沒有執行工作的邏輯操作的對象;如果後續操作可以以更有效的方式進行組合,則可以這樣做。它只是在賦值給一個具體類型時,表達式被解析/計算(通過隱式轉換),這可以減少工作(例如,對於1000+位,計算'(a * b)&1'可能是昂貴的) '/'b',但表達式模板可以分配'&1',因此乘法是在一個位上。 – ShadowRanger