MATLAB矩阵乘法vs for每个列的循环

MATLAB矩阵乘法vs for每个列的循环,matlab,matrix-multiplication,Matlab,Matrix Multiplication,将两个矩阵相乘时,我尝试了以下两个选项: (一) (二) 我为这两个中的res预先分配了内存。令人惊讶的是,我发现选项2更快 有人能解释为什么会这样吗 编辑: 我试过了 在我看来,你并没有正确地乘以矩阵,你需要求X矩阵第i行和矩阵第j列的所有乘积之和,这可能是一个原因。 看看它是如何完成的。这很可能是缓存的一种效果在执行第二个版本时,缓存中已经存在一个,因此它具有优势。尝试创建一组独立的输入以使其公平。此外,为了消除由于外部影响而产生的典型变化,可能最好测量例如100万次迭代的时间。我在一个循环

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

(一)

(二)

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

有人能解释为什么会这样吗

编辑: 我试过了


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

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

我在一个循环中运行这两个代码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

因此,永远不要基于一次跑步得出计时结论。

我相信我可以插话说明两种方法计时的差异,以及人们获得不同相对速度的原因

在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还谈到了其他一些事情。在以下情况下,时间_1和时间_2之间通常存在差异:

tic; x = log(1:1e5); time_1 = toc
tic; x = log(1:1e5); time_2 = toc
因此,100万次评估与一次评估的测试是有价值的,这取决于x在内存中的位置(在缓存中或否)


希望这能再次帮助您。

我修改了您的代码并编辑了问题。在我的机器上,如果我在每次迭代中使用不同的x和a,第二个版本会更快。真的吗?每次迭代都会重新解释源代码?我觉得很难相信!你有这方面的引证吗?恐怕没有。这是我两年前在HPC的一次讲座中回忆到的。我编辑了这篇文章来澄清我的意思。在OSX,2010b上,我得到了版本一的时间中位数为0.0001,版本二的时间中位数为0.0008。换句话说,矢量化版本大约快7倍。为了消除一些变化,最好在开始第二次运行之前重置随机生成器。不管怎样,我还发现第一个选项的速度要快好几倍。
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
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
tic; x = log(1:1e5); time_1 = toc
tic; x = log(1:1e5); time_2 = toc