【问题标题】:Vectorizing range setting - MATLAB向量化范围设置 - MATLAB
【发布时间】:2016-12-15 04:16:06
【问题描述】:

我有以下代码。我需要重写它而不循环。我该怎么做?

l1 = [1 2 3 2 1];
l2 = [3 4 4 5 4];
A = zeros(5,5);
for i=1:5
    A(i, l1(i):l2(i)) = 1;
end

A

【问题讨论】:

  • 为什么需要重写?是不是太慢了?
  • :D 你知道,如果你用对了,这实际上是一个好问题
  • @Jørgen 是的,它很慢。实际上矩阵大小很大,我有几个类似于上面的操作。这只是一个示例,并已尽可能简化。

标签: performance matlab vectorization


【解决方案1】:

你可以使用bsxfun -

I = 1:5 % Array corresponding to iterator : "for i=1:5"
out = bsxfun(@le,l1(:),I) & bsxfun(@ge,l2(:),I)

如果你需要一个双精度数据类型数组,就转换成双精度,像这样 -

out_double = double(out)

【讨论】:

  • 很好,看到您不需要完整的坐标网格,因为 bsxfun 会自动扩展 1:5。请注意,此答案确实返回了一个逻辑(这可能是一件好事,但与循环不同)。
  • @DennisJaheruddin 编辑解决方案以满足该要求。
【解决方案2】:

然后再添加一个!这个简单地使用一个 cumsum 来生成所有的 1 - 所以它根本不使用 : 运算符 - 它也是完全并行的:D

l1 = [1 2 3 2 1];
l2 = [3 4 4 5 4];
A = zeros(5,5);

L1 = l1+(1:5)*5-5; %Convert to matrix location index
L2 = l2+(1:5)*5-5; %Convert to matrix location index
A(L1) = 1;         %Place 1 in that location
A(L2) = 1;         %Place 1 in that location

B = cumsum(A,1) ==1 ;   %So fast
Answer = (A|B)';        %Lightning fast

Answer =

 1     1     1     0     0
 0     1     1     1     0
 0     0     1     1     0
 0     1     1     1     1
 1     1     1     1     0

【讨论】:

    【解决方案3】:

    这是不使用循环构建矩阵的方法。

    % Our starting values
    l1 = [1 2 3 2 1];
    l2 = [3 4 4 5 4];
    
    % Coordinate grid of the right size (we don't need r, but I keep it there for illustration)
    [r,c] = ndgrid(1:5);
    
    % Build the logical index based on our lower and upper bounds on the column indices
    idx_l1=bsxfun(@ge,c,l1');
    idx_l2=bsxfun(@le,c,l2');
    
    % The result
    A = zeros(size(idx_l1));
    A(idx_l1&idx_l2)=1
    

    您可能需要[r,c] = ndgrid(1:numel(l1),1:10) 之类的东西。

    此外,如果您的矩阵大小确实很大并且内存成为问题,您可能仍希望坚持循环,但对于“正常大小”,这可能会更快。

    【讨论】:

      【解决方案4】:

      每个向量化都应该有一些怀疑。如果您测量时间,实际上您的循环比给定的答案要快,主要是因为您只执行就地写入。

      这是另一种对于更大尺寸可能会更快但我没有测试过的方法:

      tic
      myind = [];
      for i = 1:5
          myind = [myind (5*(i-1))+[l1(i):l2(i)]];
      end
      A(myind) = 1;
      toc
      

      由于线性索引顺序,给出了转置的A

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-08-31
        • 1970-01-01
        • 1970-01-01
        • 2016-01-21
        • 2016-04-30
        相关资源
        最近更新 更多