【发布时间】:2015-08-05 04:34:22
【问题描述】:
在我的工作(计量经济学/统计学)中,我经常需要将不同大小的矩阵相乘,然后对生成的矩阵执行额外的操作。我一直依赖bsxfun() 对代码进行矢量化处理,总的来说我发现它比repmat() 更有效。但我不明白的是,为什么有时bsxfun() 的性能在沿不同维度扩展矩阵时会非常不同。
考虑这个具体的例子:
x = ones(j, k, m);
beta = rand(k, m, s);
exp_xBeta = zeros(j, m, s);
for im = 1 : m
for is = 1 : s
xBeta = x(:, :, im) * beta(:, im, is);
exp_xBeta(:, im, is) = exp(xBeta);
end
end
y = mean(exp_xBeta, 3);
上下文:
我们有来自 m 个市场的数据,在每个市场中,我们想要计算 exp(X * beta) 的期望值,其中 X 是j x k 矩阵,beta 是 k x 1 随机向量.我们通过 monte-carlo 积分来计算这个期望值 - 对 beta 进行 s 次绘制,为每次绘制计算 exp(X * beta),然后取平均值。通常我们使用 m > k > j 获取数据,并且我们使用非常大的 s。在这个例子中,我只是让 X 成为一个矩阵。
我使用bsxfun() 进行了 3 个版本的矢量化,它们的不同之处在于 X 和 beta 的形状:
矢量化 1
x1 = x; % size [ j k m 1 ]
beta1 = permute(beta, [4 1 2 3]); % size [ 1 k m s ]
tic
xBeta = bsxfun(@times, x1, beta1);
exp_xBeta = exp(sum(xBeta, 2));
y1 = permute(mean(exp_xBeta, 4), [1 3 2 4]); % size [ j m ]
time1 = toc;
矢量化 2
x2 = permute(x, [4 1 2 3]); % size [ 1 j k m ]
beta2 = permute(beta, [3 4 1 2]); % size [ s 1 k m ]
tic
xBeta = bsxfun(@times, x2, beta2);
exp_xBeta = exp(sum(xBeta, 3));
y2 = permute(mean(exp_xBeta, 1), [2 4 1 3]); % size [ j m ]
time2 = toc;
矢量化 3
x3 = permute(x, [2 1 3 4]); % size [ k j m 1 ]
beta3 = permute(beta, [1 4 2 3]); % size [ k 1 m s ]
tic
xBeta = bsxfun(@times, x3, beta3);
exp_xBeta = exp(sum(xBeta, 1));
y3 = permute(mean(exp_xBeta, 4), [2 3 1 4]); % size [ j m ]
time3 = toc;
这就是他们的表现(通常我们使用 m > k > j 获取数据,并且我们使用了非常大的 s):
j = 5,k = 15,m = 100,s = 2000:
For-loop version took 0.7286 seconds.
Vectorized version 1 took 0.0735 seconds.
Vectorized version 2 took 0.0369 seconds.
Vectorized version 3 took 0.0503 seconds.
j = 10,k = 15,m = 150,s = 5000:
For-loop version took 2.7815 seconds.
Vectorized version 1 took 0.3565 seconds.
Vectorized version 2 took 0.2657 seconds.
Vectorized version 3 took 0.3433 seconds.
j = 15,k = 35,m = 150,s = 5000:
For-loop version took 3.4881 seconds.
Vectorized version 1 took 1.0687 seconds.
Vectorized version 2 took 0.8465 seconds.
Vectorized version 3 took 0.9414 seconds.
为什么版本 2 始终是最快的版本?最初,我认为性能优势是因为 s 设置为维度 1,Matlab 可能能够更快地计算,因为它以列优先顺序存储数据。但 Matlab 的分析器告诉我,计算该平均值所花费的时间相当微不足道,并且在所有 3 个版本中或多或少相同。 Matlab 大部分时间都在评估 bsxfun() 行,这也是 3 个版本中运行时差异最大的地方。
有没有想过为什么版本 1 总是最慢而版本 2 总是最快?
我在这里更新了我的测试代码: Code
编辑:这篇文章的早期版本不正确。 beta 的大小应为 (k, m, s)。
【问题讨论】:
标签: performance matlab matrix vectorization bsxfun