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
调用移到循环内外,没有太多变化。临时内存被重新使用。
我已经在 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
调用移到循环内外,没有太多变化。临时内存被重新使用。