2016-08-02 47 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