2011-03-02 284 views
2

在循環的每次迭代中,我正在計算一個MATLAB矩陣。這些矩陣必須連接在一起以創建一個最終矩陣。我在進入循環之前知道這個最終矩陣的維數,所以我通過使用'零'函數預分配矩陣比初始化一個空數組要快,然後在我的循環的每次迭代中簡單地追加子陣列。奇怪的是,當我預先分配時,我的程序運行速度很慢。下面是代碼(只有第一個和最後一個行不同):MATLAB矩陣預分配比動態矩陣擴展慢

這是慢:

w_cuda = zeros(w_rows, w_cols, f_cols); 

for j=0:num_groups-1 

    % gets # of rows & cols in W. The last group is a special 
    % case because it may have fewer than max_row_size rows 
    if (j == num_groups-1 && mod(w_rows, max_row_size) ~= 0) 
     num_rows_sub = w_rows - (max_row_size * j);  
    else 
     num_rows_sub = max_row_size; 
    end; 

    % calculate correct W and f matrices 
    start_index = (max_row_size * j) + 1; 
    end_index = start_index + num_rows_sub - 1; 

    w_sub = W(start_index:end_index,:); 
    f_sub = filterBank(start_index:end_index,:); 

    % Obtain sub-matrix 
    w_cuda_sub = nopack_cu(w_sub,f_sub); 

    % Incorporate sub-matrix into final matrix 
    w_cuda(start_index:end_index,:,:) = w_cuda_sub; 

end 

這是快:

w_cuda = []; 

for j=0:num_groups-1 

    % gets # of rows & cols in W. The last group is a special 
    % case because it may have fewer than max_row_size rows 
    if (j == num_groups-1 && mod(w_rows, max_row_size) ~= 0) 
     num_rows_sub = w_rows - (max_row_size * j);  
    else 
     num_rows_sub = max_row_size; 
    end; 

    % calculate correct W and f matrices 
    start_index = (max_row_size * j) + 1; 
    end_index = start_index + num_rows_sub - 1; 

    w_sub = W(start_index:end_index,:); 
    f_sub = filterBank(start_index:end_index,:); 

    % Obtain sub-matrix 
    w_cuda_sub = nopack_cu(w_sub,f_sub); 

    % Incorporate sub-matrix into final matrix 
    w_cuda = [w_cuda; w_cuda_sub]; 

end 

至於其他潛在有用的信息 - 我矩陣是3D的,其中的數字很複雜。一如往常,任何見解都被讚賞。

+0

部分似乎缺少。矩陣或函數「W」和「filterBank」沒有定義。 – Miebster 2011-03-02 17:52:44

+0

是的,這只是我認爲相關的代碼的一部分。謝謝。 – nedblorf 2011-03-02 18:08:30

+0

不知道你的代碼在做什麼,或者至少有一些可執行的類比你的代碼在做什麼,如何能告訴你爲什麼它很慢?從你的代碼來看,如果W,filterBank和nopack_cu都是函數或函數,就不清楚了。似乎w_rows,w_cols,f_cols,num_groups,max_row_size以某種方式相互關聯,但不清楚。 如果你可以提供一個可執行的例子,我可以進一步看看它。我懷疑在我的機器上,頂部的例子會比底部例子執行得更快。 – Miebster 2011-03-02 18:27:07

回答

7

我一直認爲預分配對於任何數組大小都更快,並且從未實際測試過它。所以,我做了一個簡單的測試,通過追加和預分配方法,使用1000次迭代計算不同數組大小的數量,從1x1x3到20x20x3。下面的代碼:

arraySize = 1:20; 
numIteration = 1000; 

timeAppend = zeros(length(arraySize), 1); 
timePreAllocate = zeros(length(arraySize), 1); 

for ii = 1:length(arraySize); 
    w = []; 
    tic; 
    for jj = 1:numIteration 
     w = [w; rand(arraySize(ii), arraySize(ii), 3)]; 
    end 
    timeAppend(ii) = toc; 
end; 

for ii = 1:length(arraySize); 
    w = zeros(arraySize(ii) * numIteration, arraySize(ii), 3); 
    tic; 
    for jj = 1:numIteration 
     indexStart = (jj - 1) * arraySize(ii) + 1; 
     indexStop = indexStart + arraySize(ii) - 1; 
     w(indexStart:indexStop,:,:) = rand(arraySize(ii), arraySize(ii), 3); 
    end 
    timePreAllocate(ii) = toc; 
end; 

figure; 
axes; 
plot(timeAppend); 
hold on; 
plot(timePreAllocate, 'r'); 
legend('Append', 'Preallocate'); 

這裏是(預期)結果:你的代碼的 Comparison of array appending vs. preallocation

+0

謝謝你這個優秀的回答。事實證明,我沒有運行足夠多的迭代來查看預分配的性能優勢。但是,當我預先分配時,我的程序運行速度較慢,達到1-5次迭代,這很不幸是一種常見用例。 – nedblorf 2011-03-07 16:39:43

+0

我想你可以在你的預分配中添加一個條件語句,只在特定的迭代閾值以上執行它。 – Eric 2011-03-15 14:36:02