簡體   English   中英

在MATLAB中'for'循環與矢量化

[英]'for' loop vs vectorization in MATLAB

我在MATLAB中編程,並且按照建議,我總是嘗試使用矢量化。 但最終該計划相當緩慢。 所以我發現在一個地方使用循環時代碼明顯更快(例如下面的例子)。

我想知道我是否誤解了某些內容或做錯了什么,因為在這種情況下性能很重要,而且我不想繼續猜測矢量化或循環是否會更快。

% data initialization

k = 8;
n = 2^k+1;
h = 1/(n-1);
cw = 0.1;

iter = 10000;

uloc = zeros(n);
fploc = uloc;
uloc(2:end-1,2:end-1) = 1;
vloc = uloc;
ploc = ones(n);

uloc2 = zeros(n);
fploc2 = uloc2;
uloc2(2:end-1,2:end-1) = 1;
vloc2 = uloc2;
ploc2 = ones(n);

%%%%%%%%%%%%%%%%%%%%%%
% vectorized version %
%%%%%%%%%%%%%%%%%%%%%%
tic
for it=1:iter
    il=2:4;
    jl=2:4;
    fploc(il,jl) = h/6*(-uloc(il-1,jl-1) + uloc(il-1,jl)...
        -2*uloc(il,jl-1)+2*uloc(il,jl+1)...
        -uloc(il+1,jl) + uloc(il+1,jl+1)...
        ...
        -vloc(il-1,jl-1) - 2*vloc(il-1,jl)...
        +vloc(il,jl-1) - vloc(il,jl+1)...
        + 2*vloc(il+1,jl) + vloc(il+1,jl+1))...
        ...
        +cw*h^2*(-ploc(il-1,jl)-ploc(il,jl-1)+4*ploc(il,jl)...
        -ploc(il+1,jl)-ploc(il,jl+1));
end
toc


%%%%%%%%%%%%%%%%%%%%%%
%    loop version    %
%%%%%%%%%%%%%%%%%%%%%%
tic
for it=1:iter
    for il=2:4
        for jl=2:4
            fploc2(il,jl) = h/6*(-uloc2(il-1,jl-1) + uloc2(il-1,jl)...
                -2*uloc2(il,jl-1)+2*uloc2(il,jl+1)...
                -uloc2(il+1,jl) + uloc2(il+1,jl+1)...
                ...
                -vloc2(il-1,jl-1) - 2*vloc2(il-1,jl)...
                +vloc2(il,jl-1) - vloc2(il,jl+1)...
                + 2*vloc2(il+1,jl) + vloc2(il+1,jl+1))...
                ...
                +cw*h^2*(-ploc2(il-1,jl)-ploc2(il,jl-1)+4*ploc2(il,jl)...
                -ploc2(il+1,jl)-ploc2(il,jl+1));
        end
    end
end
toc

我沒有查看你的代碼,但最近版本的Matlab中的JIT編譯器已經改進到你所面臨的情況非常普遍 - 循環可以比矢量化代碼更快。 事先很難知道哪個會更快,所以最好的方法是以最自然的方式編寫代碼,對其進行分析,然后如果存在瓶頸,嘗試從循環切換到矢量化(或其他方式)。

MATLAB的即時編譯器(JIT)在過去幾年中得到了顯着改善。 即使你是對的,通常也應該對代碼進行矢量化,根據我的經驗,這僅適用於某些操作和函數,還取決於函數處理的數據量。

找到最佳方法的最佳方法是使用和不使用矢量化來分析MATLAB代碼

也許一些元素的矩陣不是矢量化效率的良好測試。 最終,它取決於應用程序的運行情況。

此外,通常矢量化代碼看起來更好(對底層模型更真實),但在很多情況下它沒有,並且最終會損害實現。 你所做的很棒,因為現在你知道什么最適合你。

我不會稱之為矢量化。

您似乎正在進行某種過濾操作。 這種濾波器的真正矢量化版本是原始數據,乘以濾波器矩陣(即,代表整個for循環的一個矩陣)。

這些矩陣的問題在於它們非常稀疏(對角線周圍只有少數非零元素),使用它們幾乎沒有效率。 您可以使用sparse命令,但即便如此,符號的優雅可能並不能證明所需的額外內存。

Matlab以前對for循環不好,因為即使循環計數器等仍被視為復雜矩陣,因此在每次迭代時都會對所有矩陣的檢查進行評估。 我的猜測是,在你的for循環中,每次應用濾波器系數時仍會執行所有這些檢查。

也許matlab函數filterfilter2在這里很有用? 您也可以閱讀這篇文章: 改進MATLAB矩陣構造代碼:或者,代碼矢量化為begginers

一種可能的解釋是啟動開銷。 如果在場景后面創建臨時矩陣,請准備好進行內存分配。 另外,我猜MATLAB不能推斷你的矩陣很小,所以會有循環開銷。 所以你的矢量化版本最終可能會像代碼一樣

double* tmp=(double*)malloc(n*sizeof(double));
for(size_t k=0;k<N;++k)
    {
//  Do stuff with elements
    }
free(tmp);

將此與已知數量的操作進行比較:

double temp[2];
temp[0]=...;
temp[1]=...;

因此,當malloc-loopcounter-free時間長於每次計算的工作負載時,JIT可能會更快。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM