MATLAB矩阵乘法与每列的循环

时间:2011-02-06 20:52:42

标签: matlab matrix-multiplication

当乘以两个矩阵时,我尝试了以下两个选项:

1)

res = X*A;

2)

for i = 1:size(A,2)
    res(:,i) = X*A(:,i);
end

我在两者中预先分配了res的内存。令人惊讶的是,我发现选项2更快。

有人能解释一下这是怎么回事吗?

编辑: 我试过了

K=10000;
clear t1 t2
t1=zeros(K,1);
t2=zeros(K,1);

for k=1:K
    clear res
    x = rand(100,100);
    a = rand(100,100);
    tic
    res = x*a;
    t1(k) = toc;
end

for k=1:K
    clear res2
    res2 = zeros(100,100);
    x = rand(100,100);
    a = rand(100,100);
    tic
    for i = 1:100
        res2(:,i) = x*a(:,i);
    end
    t2(k) = toc;
end

4 个答案:

答案 0 :(得分:3)

我在循环中运行两个代码1000次。平均而言(但并非总是如此),第一个矢量化代码的速度提高了3-4倍。我清除了结果变量并在启动计时器之前预分配。

x = rand(100,100);
a = rand(100,100);

K=1000;
clear t1 t2
t1=zeros(K,1);
t2=zeros(K,1);

for k=1:K
    clear res
    tic
    res = x*a;
    t1(k) = toc;
end

for k=1:K
    clear res2
    res2 = zeros(100,100);
    tic
    for i = 1:100
        res2(:,i) = x*a(:,i);
    end
    t2(k) = toc;
end

因此,永远不要基于单次运行得出时间结论。

答案 1 :(得分:2)

这很可能是缓存的影响。在您执行第二个版本时,a已经在缓存中,因此它具有优势。尝试创建一组独立的输入以使其公平。而且,测量例如时间可能更好。 100万次迭代,以消除由于外部效应引起的典型变化。

答案 2 :(得分:2)

我相信我可以了解两种方法之间的时间差异,以及人们获得不同相对速度的原因。

在Matlab版本2008a(或该版本附近的版本)之前,for循环在任何Matlab代码中都受到重创,因为解释器(非常易读的脚本和代码的低级实现之间的层)必须重新编写 - 每次通过for循环解释代码。

从那个版本开始,解释器逐渐变得更好,所以当运行现代版本的Matlab时,解释器可以查看你的代码并说“啊哈!我知道他在做什么,让我稍微优化一下“并且通过重新解释代码来避免它可能会遭受的打击。

我希望在相同的时间内执行矩阵乘法的两种方法,为什么for循环实现运行得更快是因为解释器的优化中的一些细节,我们凡人都不知道。

我们应该从中学到一个广泛的教训,并非所有版本都是平等的。我使用两个Matlab附件,SimBiology和并行计算工具箱来处理几个前沿案例,这两个案例(特别是如果你想让它们一起工作)都依赖于版本执行的速度,并且不时其他稳定性问题。因此,我保留了Matlab的三个最新版本,将测试我从每个版本得到相同的答案,如果我发现某些功能的问题,我偶尔会回滚到早期版本。这对大多数人来说可能有些过分,但可以让您了解版本差异。

希望这有帮助。

编辑:

为了澄清,代码矢量化仍然很重要。但是给出了一个类似的脚本:

x_slow = zeros(1,1e5);
x_fast = zeros(1,1e5);


tic;
for i=1:1e5
    x_slow(i) = log(i);
end
time_slow = toc; % evaluates for me in .0132 seconds

tic;
x_fast = log(1:1e5);
time_fast = toc; % evaluates for me in .0055 seconds

基于解释器的改进,time_slow和time_fast之间的差异在过去的几个版本中有所减少。我看到的例子是2000a与2008b相比,但这取决于我的回忆。

Oli和Yuk解决了其他可能发生的问题。 time_1和time_2之间通常存在差异:

tic; x = log(1:1e5); time_1 = toc
tic; x = log(1:1e5); time_2 = toc

因此,对一百万次评估与一次评估的测试是有价值的,具体取决于内存x的位置(缓存中或否)。

希望这会有所帮助。

答案 3 :(得分:-3)

在我看来,你没有正确地乘以矩阵,你需要将来自X矩阵的第i行和A矩阵的第j列的所有乘积相加,这可能是一个原因。 看here看看它是如何完成的。