在MATLAB中重塑矢量

时间:2016-05-02 20:39:32

标签: performance matlab

我正在尝试在MATLAB中使用单个for循环实现BlockLMS。为此,给定一个向量 u ,我试图创建一个表格

U = [u(k)     u(k+1)     u(k+2)  ...    u(k+n)
     u(k-1)   u(k)       ...     ...    u(k+n-1)
     ...      ...        ...     ...    ...
     u(k-n)   u(k-n+1)   ...     ...    u(k)]

其中 n 是一个常量, k 是一个随每个for循环而变化的变量,始终为k > n。到目前为止我所取得的成就是:

index = meshgrid(0:-1:1-n)' + meshgrid(1:n);
for i = 2:q
    % calculate k
    U = u(k + index);
    % rest of code goes here
end

虽然它有效,但遗憾的是很慢,并不适合我的需要。有没有更有效的方法来实现这一结果?

3 个答案:

答案 0 :(得分:6)

您可以使用toeplitz

内置的单线程
 toeplitz(20:-1:15,20:25)

ans =

20    21    22    23    24    25
19    20    21    22    23    24
18    19    20    21    22    23
17    18    19    20    21    22
16    17    18    19    20    21
15    16    17    18    19    20

或者,以更通用的方式:

f = @(k,n)toeplitz(k:-1:k-n,k:k+n)

然后您可以编写U=u(f(k,n))来获取问题中的通用表单。 但请检查一下这是否确实比你的for循环更快。

编辑:toeplitz的内部机制是bsxfun,所以我猜想除非你在较低级别的c \ fortran中意识到这一点,否则这就好了。检查edit toeplitz并查看其实施方式......

答案 1 :(得分:4)

这应该有效:

k = 20;     % Example k
n = 5;      % Example n < k

u = 1:50;   % Example vector

[x, y] = meshgrid(0:n,k:-1:k-n);
U = u(x+y)   % Use x+y as index
U =

   20   21   22   23   24   25
   19   20   21   22   23   24
   18   19   20   21   22   23
   17   18   19   20   21   22
   16   17   18   19   20   21
   15   16   17   18   19   20

如您所见,左上角是元素编号k,右上角是元素编号k+n,左下角是k-n,右下角是元素{{ 1}}。

答案 2 :(得分:4)

该操作有很多重复。所以,为了利用这种性质,这里有一种使用imagerotate的方法和repmat屏蔽功能的一点帮助 -

mask = bsxfun(@ge,(1:2*n+1)',n+1:-1:1) & bsxfun(@ge,(2*n+1:-1:1)',1:n+1)
sliced_u = u(k+n:-1:k-n)
repvals = repmat(sliced_u(:),1,n+1)
out = reshape(repvals(mask),n+1,[])

当人们沿着列复制输入u的柱状版本时,我们可以向右移动一个位置时,可以用来描述所需输出的列。 。剩下的工作是抵消沿着柱子移动的一个位置,这是通过bsxfun的遮蔽来切断上下三角形区域以给出最终输出。

效果:此问题之前已被利用bsxfun's中的类似问题,我希望此处有相似的效果数字。

作为另一种方法并直接思考,可以使用bsxfun来获取2D索引,然后为最终输出索引u,就像这样 -

out = u(bsxfun(@plus,(k:-1:k-n)',0:n))