为什么x \ y比(x' * x)\(x' * y)慢得多?

时间:2014-04-03 08:54:47

标签: performance matlab

对于NxP矩阵x和Nx1向量y,其中N> P,两个表达式

x \ y                                       -- (1)

(x' * x) \ (x' * y)                         -- (2)

计算解决方案b到矩阵方程

x * b = y

在最小二乘意义上,即使得数量

norm(y - x * b)

最小化。表达式(2)使用经典算法来解决普通最小二乘回归,其中\运算符的左手参数是正方形。它相当于写作

inv(x' * x) * (x' * y)                      -- (3)

但它使用的算法在数值上更稳定。事实证明,(3)比(2)适度快,即使(2)不必产生作为副产品的逆矩阵,但我可以接受给定的额外数值稳定性。

然而,一些简单的时间(N = 100,000和P = 30)表明表达式(2)比表达式(1)快5倍以上,即使(1)具有更大的灵活性来选择所使用的算法!例如,对(1)的任何调用都可以只调度X的大小,并且在N> P的情况下它可以减少到(2),这会增加很少的开销,但肯定不会5倍。

表达式(1)中发生了什么导致它花费更长时间?


编辑:这是我的时间

x = randn(1e5, 30);
y = randn(1e5,1);
tic, for i = 1:100; x\y; end; t1=toc;
tic, for i = 1:100; (x'*x)\(x'*y); end; t2=toc;
assert( abs(norm(x\y) - norm((x'*x)\(x'*y))) < 1e-10 );
fprintf('Speedup: %.2f\n', t1/t2)

加速:5.23

2 个答案:

答案 0 :(得分:5)

你知道你的考试中的事实

size(x) == [1e5  30]    but   size(x'*x) == [30  30]
size(y) == [1e5   1]    but   size(x'*y) == [30   1]

这意味着进入mldivide函数的矩阵的大小 大小不等4个数量级! 这会产生确定使用哪种算法的任何开销相当大和重要(也许还在两个不同的问题上运行相同的算法)。

换句话说,你有一个有偏见的考试。要进行合理测试,请使用类似

的内容
x = randn(1e3);
y = randn(1e3,1);

我发现(最差的5次运行):

Speedup: 1.06  %// R2010a
Speedup: 1.16  %// R2010b
Speedup: 0.97  %// R2013a

......差异已经消失了。

但是,这确实表明,如果你确实有一个与观察数量相比维度较低的回归问题,那么首先进行乘法确实是值得的:)

mldivide是一个包罗万象,真的很棒。但通常情况下,有关于问题的知识可能会产生更多特定的解决方案,例如预乘,预处理,luqr,{ {1}}等等数量级更快。

答案 1 :(得分:2)

  

即使(1)具有更大的灵活性来选择使用的算法!   例如,对(1)的任何调用都可以调度X的大小,并且   在N> P的情况下,它可以减少到(2),这将增加很小的量   开销,但肯定不会花费5倍。

事实并非如此。选择使用哪种算法可能需要很多开销,特别是与相对较小的输入(例如这些)的计算相比时。在这种情况下,因为MATLAB可以看到你有x'*x,它知道其中一个参数必须是正方形和对称(是的 - 线性代数的知识内置于MATLAB中即使在解析器级别),也可以直接调用\中的一个适当的代码路径。

我不能说这是否完全解释了你所看到的时间差异。我想进一步调查,至少是:

  1. 确保将代码放入函数中,并将函数升温以确保JIT已启用 - 然后使用feature('accel', 'off')尝试相同的操作以消除JIT的影响
  2. 在更大范围的输入大小上尝试此操作,以检查“算法选择开销”与计算时间相比所做的贡献。