我寫了一段時間的MATLAB腳本,但仍然不明白它是如何工作的「引擎蓋下」。考慮下面的腳本,它使用(大)向量以三種不同的方式進行一些計算:MATLAB快速(分量)矢量操作...真的很快
- MATLAB矢量操作;
- 簡單的循環,組件明智地做相同的計算;
- 一個優化週期,應該比2.快,因爲避免了一些分配和一些分配。
下面是代碼:
N = 10000000;
A = linspace(0,100,N);
B = linspace(-100,100,N);
C = linspace(0,200,N);
D = linspace(100,200,N);
% 1. MATLAB Operations
tic
C_ = C./A;
D_ = D./B;
G_ = (A+B)/2;
H_ = (C_+D_)/2;
I_ = (C_.^2+D_.^2)/2;
X = G_ .* H_;
Y = G_ .* H_.^2 + I_;
toc
tic
X;
Y;
toc
% 2. Simple cycle
tic
C_ = zeros(1,N);
D_ = zeros(1,N);
G_ = zeros(1,N);
H_ = zeros(1,N);
I_ = zeros(1,N);
X = zeros(1,N);
Y = zeros(1,N);
for i = 1:N,
C_(i) = C(i)/A(i);
D_(i) = D(i)/B(i);
G_(i) = (A(i)+B(i))/2;
H_(i) = (C_(i)+D_(i))/2;
I_(i) = (C_(i)^2+D_(i)^2)/2;
X(i) = G_(i) * H_(i);
Y(i) = G_(i) * H_(i)^2 + I_(i);
end
toc
tic
X;
Y;
toc
% 3. Opzimized cycle
tic
X = zeros(1,N);
Y = zeros(1,N);
for i = 1:N,
X(i) = (A(i)+B(i))/2 * ((C(i)/A(i) + D(i)/B(i)) /2);
Y(i) = (A(i)+B(i))/2 * ((C(i)/A(i) + D(i)/B(i)) /2)^2 + ((C(i)/A(i))^2 + (D(i)/B(i))^2)/2;
end
toc
tic
X;
Y;
toc
我知道一個應該總是試圖向量化計算,是MATLAB建立了矩陣/矢量(因此,如今,它並不總是最好的選擇),所以我期待的東西,如:
C = A .* B;
快於:
for i in 1:N,
C(i) = A(i) * B(i);
end
我是而不是即使在上面的腳本中,儘管我使用的第二個和第三個方法只經歷了一個循環,但第一個方法執行了許多向量操作(理論上,每次都是「for」循環)。這種力量我得出結論MATLAB有一些神奇的允許(例如)到:
C = A .* B;
D = C .* C;
要運行多單「表示」裏面的一些操作週期更快。
所以:
- 什麼魔術這避免了第1部分中執行得這麼快?
- 當你寫「D = A * B」時,MATLAB實際上是用一個「for」循環做一個組件明智的計算,還是簡單地跟蹤D包含「bla」和「bla」的一些乘法?
編輯
- 假設我要實現相同的計算使用C++(使用也許有些庫)。將會是第一種MATLAB的方法比在C++中實現的第三種方法更快嗎? (我會回答這個問題我自己,給我一些時間。)
EDIT 2
按照要求,這裏有實驗運行時間:
1部分:0.237143
第2部分:4.440132 其中0。195154用於分配
3部分:
1部分:其中0.057500用於分配
和沒有JIT 2.280640 的0.337259
第2部分:其中0.033886用於分配
149.602017 的第3部分:82.167713 其中0.010852分配
請您用實測的計算時間來補充您的實驗。 – zellus
+1,我期待着答案! =) –
魔術是JIT加速器([just just time compilation](http://en.wikipedia.org/wiki/Just-in-time_compilation))。在運行'feature('accel','off')後嘗試你的代碼' - 我警告你,這將需要一段時間。不要忘記用'feature'('accel','on')'把它重新打開。 – horchler