[英]2D Vector Optimization
這只是一個緊湊的測試用例,但是我有一個double的向量,並且我想填充所有成對差異的方陣(2D向量)。 使用-O3優化進行編譯時,這在我的計算機上大約需要1.96秒(僅從嵌套的double for循環計算)。
#include <vector>
using namespace std;
int main(){
vector<double> a;
vector<vector<double> > b;
unsigned int i, j;
unsigned int n;
double d;
n=10000; //In practice, this value is MUCH bigger
a.resize(n);
for (i=0; i< n; i++){
a[i]=static_cast<double>(i);
}
b.resize(n);
for (i=0; i< n; i++){
b[i].resize(n);
b[i][i]=0.0; //Zero diagonal
}
for (i=0; i< n; i++){
for (j=i+1; j< n; j++){
d=a[i]-a[j];
//Commenting out the next two lines makes the code significantly faster
b[i][j]=d;
b[j][i]=d;
}
}
return 0;
}
但是,當我注釋掉這兩行時:
b[i][j]=d;
b[j][i]=d;
該程序將在大約0.000003秒內完成(僅從嵌套的double for循環計算)! 我真的沒想到這兩行是限速步驟。 我盯着這段代碼已經有一段時間了,我沒有想法。 任何人都可以就如何優化此簡單代碼段提供任何建議,以便可以大大減少時間嗎?
當您注釋掉這兩行時,嵌套循環中剩下的就是繼續計算d
,然后丟棄結果。 由於這對程序的行為沒有任何影響,因此編譯器將優化嵌套循環。 這就是程序幾乎立即完成的原因。
實際上,我使用g++ -O3
兩次編譯了代碼,一次在嵌套循環中僅使用d=a[i]-a[j]
語句,一次將嵌套循環完全刪除,從而證實了這一點。 發出的代碼是相同的。
但是,由於缺少高速緩存,因此您的代碼當前比必須的慢。 當您像這樣在嵌套循環中訪問二維數組時,應盡可能安排迭代在內存中連續進行。 這意味着第二個索引應該是變化更快的索引。 對b[j][i]
的訪問違反了此規則,並且缺少緩存。 因此,讓我們重寫。
之前:
for (i=0; i< n; i++){
for (j=i+1; j< n; j++){
d=a[i]-a[j];
b[i][j]=d;
b[j][i]=d;
}
}
定時:
real 0m1.026s
user 0m0.824s
sys 0m0.196s
后:
for (i = 0; i < n; i++) {
for (j = 0; j < i; j++) {
b[i][j] = a[j] - a[i];
}
for (j = i+1; j < n; j++) {
b[i][j] = a[i] - a[j];
}
}
定時:
real 0m0.335s
user 0m0.164s
sys 0m0.164s
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.