【问题标题】:How to profile a vector outer product in matlab如何在matlab中分析向量外积
【发布时间】:2023-04-08 16:51:02
【问题描述】:

在我的 matlab 分析过程中,我注意到一行代码消耗的时间比我想象的要多得多。知道如何让它更快吗?

X = Y(ids_A, ids_A) - (Y(ids_A,k) * Y(k,ids_A))/Y(k,k); 

X 和 Y 是具有相同大小 (dxd) 的对称矩阵,k 是 Y 中单个行/列的索引,ids_A 是所有其他行/列的索引向量(因此 Y(ids_A, k) 是列向量,Y(k,ids_A) 是行向量)

ids_A = setxor(1:d,k); 

谢谢!

【问题讨论】:

  • 嗯。您是否考虑过使用数学的力量?看起来这应该是某些给定数学公式的一部分。你手头有什么细节吗?这是某种分解吗?
  • 我记得有一个类似的概念叫做householder transformation 用于二维码分解..

标签: matlab performance vector profiling


【解决方案1】:

您也许可以通过调用bsxfun 来替换外部乘法:

X = Y(ids_A, ids_A) - (bsxfun(@times, Y(ids_A,k), Y(k,ids_A))/Y(k,k));

那么上面的代码是如何工作的呢?我们来看看当一个向量是4个元素,其他3个元素时外积的定义:

来源:Wikipedia

如您所见,外部乘积由元素乘积创建,其中第一个向量 u 水平复制,而第二个向量 v 垂直复制。然后,您可以找到每个元素的元素乘积来产生结果。这是通过bsxfun 雄辩地完成的:

bsxfun(@times, u, v.');

u 是列向量,v.' 是行向量。 bsxfun 自然地复制数据以遵循上述模式,然后我们使用 @times 来执行 element-wise 产品。

【讨论】:

  • 非常有趣。我进行了一些快速计时实验,bsxfun 对于任何大于~100 个元素(100x100 输出)的外部产品都更快。没想到……
  • 奇数。我以为我已经看到了很多答案,其中bsxfun(@times 被划伤以支持矩阵乘法,而不是相反!可能总是行时间列sum(bsxfun(@times 类型...
  • @Raab70 这很奇怪!这是否意味着对于小矩阵,for 循环更好?如果您查看我提出的这个问题:stackoverflow.com/questions/25877835/… - 我有两个 3D 矩阵,我想计算每对矩阵切片的外积。我的输入大小小于每片100 x 100bsxfun 在时间方面是赢家。我的猜测是,这一切都归结为:(1)您拥有的 MATLAB 版本,(2)您提供的输入,(3)处理器和计算机配置。
  • @knedlsepp - 你是对的,尤其是我刚才问的这个问题:stackoverflow.com/questions/25877835/… - 我有两个 3D 矩阵,我想计算每对矩阵切片的外积。 Luis Mendo 提供的 bsxfun 方法在我的机器上运行速度最快。
  • @rayryeng:我刚刚看了看:kron 源也使用了bsxfun,所以 mathworks 的人也会同意。
【解决方案2】:

我假设你的代码看起来像这样 -

for k = 1:d
    ids_A = setxor(1:d,k);
    X = Y(ids_A, ids_A) - (Y(ids_A,k) * Y(k,ids_A))/Y(k,k);
end

使用给定的代码 sn-p,可以安全地假设您在该循环中以某种方式使用 X。您可以在此类循环开始之前计算所有X 矩阵作为预计算步骤,并且这些计算可以作为矢量化方法执行。

关于代码 sn-p 本身,可以看出您在每次迭代中使用setxor“转义”一个索引。现在,如果您使用矢量化方法,您可以在 one-go 中执行所有这些数学运算,然后删除合并到矢量化方法中但不是预期的元素。这确实是下面列出的基于 bsxfun 的矢量化方法的精髓 -

%// Perform all matrix-multiplications in one go with bsxfun and permute
mults = bsxfun(@times,permute(Y,[1 3 2]),permute(Y,[3 2 1]));

%// Scale those with diagonal elements from Y and get X for every iteration
scaledvals = bsxfun(@rdivide,mults,permute(Y(1:d+1:end),[1 3 2]));
X_vectorized = bsxfun(@minus,Y,scaledvals);

%// Find row and column indices as linear indices to be removed from X_all
row_idx = bsxfun(@plus,[0:d-1]*d+1,[0:d-1]'*(d*d+1));
col_idx = bsxfun(@plus,[1:d]',[0:d-1]*(d*(d+1)));

%// Remove those "setxored" indices and then reshape to expected size
X_vectorized([row_idx col_idx])=[];
X_vectorized = reshape(X_vectorized,d-1,d-1,d);

基准测试

基准代码

d = 50;          %// Datasize
Y = rand(d,d);    %// Create random input
num_iter = 100;   %// Number of iterations to be run for each approach

%// Warm up tic/toc.
for k = 1:100000
    tic(); elapsed = toc();
end

disp('------------------------------ With original loopy approach')
tic
for iter = 1:num_iter
    for k = 1:d
        ids_A = setxor(1:d,k);
        X = Y(ids_A, ids_A) - (Y(ids_A,k) * Y(k,ids_A))/Y(k,k);
    end
end
toc
clear X k ids_A

disp('------------------------------ With proposed vectorized approach')
tic
for iter = 1:num_iter
    mults = bsxfun(@times,permute(Y,[1 3 2]),permute(Y,[3 2 1]));
    scaledvals = bsxfun(@rdivide,mults,permute(Y(1:d+1:end),[1 3 2]));
    X_vectorized = bsxfun(@minus,Y,scaledvals);

    row_idx = bsxfun(@plus,[0:d-1]*d+1,[0:d-1]'*(d*d+1));
    col_idx = bsxfun(@plus,[1:d]',[0:d-1]*(d*(d+1)));

    X_vectorized([row_idx col_idx])=[];
    X_vectorized = reshape(X_vectorized,d-1,d-1,d);
end
toc

结果

案例#1:d = 50

------------------------------ With original loopy approach
Elapsed time is 0.849518 seconds.
------------------------------ With proposed vectorized approach
Elapsed time is 0.154395 seconds.

案例#2:d = 100

------------------------------ With original loopy approach
Elapsed time is 2.079886 seconds.
------------------------------ With proposed vectorized approach
Elapsed time is 2.285884 seconds.

案例#1:d = 200

------------------------------ With original loopy approach
Elapsed time is 7.592865 seconds.
------------------------------ With proposed vectorized approach
Elapsed time is 19.012421 seconds.

结论

人们很容易注意到,在处理大小不超过100 x 100 的矩阵时,所提出的矢量化方法可能是更好的选择 内存饥渴的 bsxfun 让我们慢下来。

【讨论】:

    猜你喜欢
    • 2016-01-09
    • 2013-01-17
    • 2011-02-21
    • 2018-05-09
    • 2014-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-29
    相关资源
    最近更新 更多