使用预定规则索引矩阵

时间:2014-07-09 03:31:52

标签: performance matlab matrix indexing

我有P <151x1 double>D <6x1 double>D的示例为[24;7;9;11;10;12]。我必须根据PD进行索引,以便在P中我希望保留6个12个元素的块,但每个块与下一个块分隔n个元素。 nD提供。 P的前12个元素是第一个块。因此,第一个块将是P(1:12),第二个块将是P(37:48,1),因为我们想在第一个块之后跳过24个元素(24是D(1,1),第三个块将保持P(56,1) {1}}因为我们想在第二个块之后跳过7个元素(7是D(2,1))等等。索引之后我最终会得到72个元素。

有没有人可以帮我找到有效索引的解决方案?

谢谢!

3 个答案:

答案 0 :(得分:3)

一种方法 -

%// Parameters
block_size = 12;
num_blocks = 6;

step_add = [0 ; cumsum(D(1:num_blocks-1))];
start_ind = [0:block_size:block_size*(num_blocks-1)]'+1 + step_add; %//'
all_valid_ind = bsxfun(@plus,start_ind,0:block_size-1)'; %//'
out = P(all_valid_ind(:)); %// desired output

请注意,您不会在计算中使用D的最后一个元素,因为D的每个元素定义了从{{1}获取的连续元素块之间的“间隙”因此,您只需要P个元素来定义5元素块之间的5个差距。


基准

循环方式from this solution

6

无循环方法(如本解决方案前面所述):

function blocks = loop1(P,D)

blocks = zeros(12, numel(D)); % //Pre-allocate blocks matrix

%// We start accessing values at 1
startIndex = 1;
%// For each index in D
for idx = 1 : numel(D)
    %// Grab the 12 elements
    blocks(:,idx) = P(startIndex : startIndex + 11);
    %// Skip over 12 elements PLUS the number specified at D
    startIndex = startIndex + 12 + D(idx);
end

return;

实际基准测试和绘图结果:

function out = no_loop1(P,D)

%// Parameters
block_size = 12;
num_blocks = numel(D);

step_add = [0 ; cumsum(D(1:num_blocks-1))];
start_ind = [0:block_size:block_size*(num_blocks-1)]'+1 + step_add; %//'
all_valid_ind = bsxfun(@plus,start_ind,0:block_size-1)'; %//'
out = P(all_valid_ind(:)); %// desired output

return;

<强>结果

enter image description here

<强>结论

此解决方案中使用的无循环方法在不同数据量范围内看起来效率更高。

答案 1 :(得分:0)

因为这是使用recurrence relation,我能看到的唯一选项是使用for循环。我们必须使用前一次迭代的输出值作为下一次迭代的输入。我个人在我的武器库中看不到任何可以进行矢量化的技术。

如果有其他人(Divakar,Luis Mendo,natan,Ben,Daniel,Amro等)可以提出更优化的解决方案,请随时回答。没有进一步的麻烦:

D = [24;7;9;11;10;12]; %// Define number of elements to skip over
blocks = zeros(12, numel(D)); % //Pre-allocate blocks matrix

%// We start accessing values at 1
startIndex = 1;
%// For each index in D
for idx = 1 : numel(D)
    %// Grab the 12 elements
    blocks(:,idx) = P(startIndex : startIndex + 11);
    %// Skip over 12 elements PLUS the number specified at D
    startIndex = startIndex + 12 + D(idx);
end

这应该为您提供12 x 6矩阵,其中每列对应于您从P中提取的元素集。作为一个小测试,我们可以显示访问P以获取元素所需的开始和结束索引。这些是通过在循环中用blocks(:,idx) = ...替换disp([startIndex startIndex + 11]);生成的。生成的指数是:

 1    12

37    48

56    67

77    88

100   111

122   133

答案 2 :(得分:0)

这可以矢量化,没问题。

    P = 1:200; % a generic P
    D = [24;7;9;11;10;12];

    D = [0 D(1:end-1)];

    basis = repmat(0:11, [6 1]);

    startingIndices = cumsum(D + 12) + 1;

    usefulIndices = bsxfun(@plus, basis, startingIndices);

    P(usefulIndices)

如果没有更多的上下文,很难建议一种“高效”地对其进行索引的方法 - 如果你只是做了几次这样的操作,代码的清晰度是最重要的。但我认为这会给你一个很好的起点。