For循环似乎比矩阵运算更快

For loop seems to be faster than a matrix operation

我已经在 logits 上工作了一段时间,为此我需要使用内置的 exp() 函数。与使用具有相同矩阵的较小块的 for 循环相比,对于大型矩阵,这似乎 运行 更慢。

在 Matlab 文档和其他几种形式中,始终建议对代码进行矢量化以加快速度。但是这里好像不是这样。

n = 32;
rows = 50000;
cols = 32;

a = rand(n*rows, cols);
b = rand(rows, cols);

% in a loop
tic
for i=1:n 
   d = exp(b);
end
toc

% big matrix
tic
d = exp(a);
toc

我预计第一个 tic-toc 会比第二个慢。但是我得到的输出如下:

Elapsed time is 0.335781 seconds.
Elapsed time is 0.390191 seconds.

任何关于为什么会出现这种情况的想法都会有所帮助。

编辑 1 假设我这样编辑我的代码以便每次都使用随机值:

n = 32;
rows = 50000;
cols = 32;

% in a loop
tic
for i=1:n 
   d = exp(rand(rows, cols));
end
toc

% big matrix
tic
e = exp(rand(n*rows, cols));
toc
return

我仍然得到:

Elapsed time is 0.745808 seconds.
Elapsed time is 0.847162 seconds.

你没有进行公平的比较:与读取更大内存块的 "big matrix" 情况相比,你的 "loop" 情况使用更少的内存,多次读取相同的较小数组,并写入更大的内存块。从主内存读取是一个瓶颈,因此能够利用缓存有助于加快 "loop" 代码。

这是一个更公平的比较:

rows = 32*50000;
cols = 32;

a = rand(rows, cols);

% in a loop
tic
d = zeros(size(a));
for i=1:cols
   d(:,i) = exp(a(:,i));
end
toc

% big matrix
tic
d = exp(a);
toc

我看到了(MATLAB R2019a 在线):

Elapsed time is 0.208699 seconds.
Elapsed time is 0.140489 seconds.

所以循环 更慢。但它并没有那么慢。在过去 15 年左右的时间里,MATLAB 一直在稳步改进他们的 JIT。在他们引入 JIT 之前,循环代码很容易慢 100 倍。

注意: 始终确保 运行 至少两次计时脚本,丢弃第一个计时。第一次 运行 某些代码时,JIT 需要对其进行编译,从而增加测量时间。


关于编辑 1:

此处您仍在处理 "loop" 情况下的较小数组。除了将 rand 调用移到循环内外,没有太多变化。临时内存被重新使用。