2016-08-02 62 views
2

考慮以下命令:如何使模數和邏輯索引工作更快?

c(c>A | c<1) = mod(c(c>A | c<1),A); 

c哪裏是一個列向量,和A是一個標量。

總之:有什麼辦法可以使這項工作更快?

說明:

c(i)表示在A -by- A矩陣的列數。但是,它可能具有大於A或小於1的值,並且此命令應以某種「PAC-MAN」方式修復它。如果c(i)大於A那麼當你到達A時從1開始倒計數,如果你再次從A開始重新從1開始,依此類推,直到你數到c(i)的值。這應該以c(i)<1的相同方式工作,所以計數將被顛倒。

實例:

  • A = 10如果和c(i) = 17,然後c(i)該命令後 應7.

  • A = 10如果和c(i) = -8,然後c(i)該命令後 應2.

  • 如果A = 10c(i) = 213,然後c(i)這個命令 後應爲3

的動機:此命令是一個仿真模型,我的一部分,它是目前在它最慢的部分。這個特定的行在模型的每個實現中被稱爲數百萬(!)次,並且有很多,所以任何改進都會有幫助。順便說一句,c的典型大小約爲10K-1。

p.s .:如果你對標題有更好的建議,我會很樂意改變它,我找不到一個好的。

回答

4

你並不需要真正做任何邏輯索引這裏因爲c > A | c < 1排除任何值將不會受到mod被感動,它很可能會以更快的速度只是傳遞一切mod,而不是做的比較和索引,以確定這些值傳遞給mod

c = [17 -8 213, 7]; 

c = mod(c, A); 
% 7 2 3 7 

雖然在一般,其他功能中,你需要輸入和功能的輸出邏輯索引,你要存儲在一個臨時變量的邏輯陣列,而不是計算了兩遍:

touse = c < 1 | c > A; 
c(touse) = mod(c(touse), A); 

這裏是表示各方法的相對性能的快速小基準:

function timemod() 

    sizes = round(linspace(100, 100000, 10)); 

    [times1, times2, times3] = deal(zeros(numel(sizes), 1)); 

    A = 10; 

    for k = 1:numel(sizes) 

     data = round(rand(sizes(k), 1) * A * 100); 
     times1(k) = timeit(@()indexing(data, A)); 

     data = round(rand(sizes(k), 1) * A * 100); 
     times2(k) = timeit(@()indexing_temp(data, A)); 

     data = round(rand(sizes(k), 1) * A * 100); 
     times3(k) = timeit(@()mod(data, A)); 
    end 

    figure 
    plot(sizes, 1000 * cat(2, times1, times2, times3)) 
    legend({'Indexing', 'Indexing w/ temp', 'No Indexing'}) 

    xlabel('Number of Elements') 
    ylabel('Execution Time (ms)') 

    fprintf('Indexing:    %0.2f ms\n', mean(times1 * 1000)) 
    fprintf('Indexing with temp: %0.2f ms\n', mean(times2 * 1000)) 
    fprintf('No Indexing or temp: %0.2f ms\n', mean(times3 * 1000)) 
end 

function data = indexing(data, A) 
    data(data > A | data < 1) = mod(data(data > A | data < 1), A); 
end 

function data = indexing_temp(data, A) 
    inds = data > A | data < 1; 
    data(inds) = mod(data(inds), A); 
end 

enter image description here

+0

這太棒了!非常感謝。我不能相信我錯過了這個選擇......現在我將盡快完成我的博士學位) – EBH

+0

你可以在第一個答案中加上第四個選項:'c1 = mod(c,A)'(賦值給另一個變量)?在我的機器中是最快的。 – EBH

+0

@EBH您是否真的用基準測試代碼測試了這個?與'c = mod(c,A)'相比,當你正確地分析它時(與'timeit'相比,不應該有真正的區別) – Suever