矢量化什么时候是比循环更好或更差的解决方案?
When does vectorization is a better or worse solution than a loop?
在 Matlab 中,我正在尝试矢量化我的代码以缩短模拟时间。然而,我得到的结果是我降低了整体效率。
为了理解这个现象,我创建了 3 个不同的函数,它们做同样的事情但方法不同:
主文件:
clc,
clear,
n = 10000;
Value = cumsum(ones(1,n));
NbLoop = 10000;
time01 = zeros(1,NbLoop);
time02 = zeros(1,NbLoop);
time03 = zeros(1,NbLoop);
for test = 1 : NbLoop
tic
vector1 = function01(n,Value);
time01(test) = toc ;
tic
vector2 = function02(n,Value);
time02(test) = toc ;
tic
vector3 = function03(n,Value);
time03(test) = toc ;
end
figure(1)
hold on
plot( time01, 'b')
plot( time02, 'g')
plot( time03, 'r')
函数 01:
function vector = function01(n,Value)
vector = zeros( 2*n,1);
for k = 1:n
vector(2*k -1) = Value(k);
vector(2*k) = Value(k);
end
end
函数 02:
function vector = function02(n,Value)
vector = zeros( 2*n,1);
vector(1:2:2*n) = Value;
vector(2:2:2*n) = Value;
end
函数 03:
function vector = function03(n,Value)
MatrixTmp = transpose([Value(:), Value(:)]);
vector = MatrixTmp (:);
end
蓝色图对应于 for - 循环。
n = 100:
n = 10000:
当我运行带有n = 100
的代码时,更有效的解决方案是第一个带有for循环的函数。
当 n = 10000
第一个函数变得效率较低。
- 您是否有办法知道如何以及何时将 for 循环正确地替换为向量化对应项?
- 使用超大维度数组进行索引搜索有何影响?
- Matlab 计算 3 维或更高维数组的方式是否与 1 维或 2 维数组不同?
- 有没有聪明的方法来替换使用迭代结果进行下一次迭代的 while 循环?
使用 MATLAB Online 我看到了不同的东西:
n 10000 100
function01 5.6248e-05 2.2246e-06
function02 1.7748e-05 1.9491e-06
function03 2.7748e-05 1.2278e-06
function04 1.1056e-05 7.3390e-07 (my version, see below)
因此,循环版本总是最慢的。方法 #2 对于非常大的矩阵更快,方法 #3 对于非常小的矩阵更快。
原因是方法#3 制作了 2 个数据副本(transpose
或一个矩阵产生了一个副本),如果数据很多,那就不好了。方法#2 使用索引,这很昂贵,但不如将大量数据复制两次那么昂贵。
我建议改为使用此函数(方法 #4),它仅转置向量(本质上是免费的)。这是对方法#3 的简单修改:
function vector = function04(n,Value)
vector = [Value(:).'; Value(:).'];
vector = vector(:);
end
Do you have a way to know how and when to properly replace a for-loop by a vectorised counterpart?
一般来说,矢量化代码总是更快如果没有大的中间矩阵。对于小数据,您可以更积极地进行向量化,对于大数据,有时由于内存压力降低,循环更有效。这取决于矢量化需要什么。
What is the impact of index searching with array of tremendous dimensions?
这里指的是d = data(data==0)
等操作。就像其他一切一样,这对小数据很有效,而对大数据则不太有效,因为 data==0
是一个与 data
.
大小相同的中间数组
Does Matlab compute in a different manner an array of dimensions 3 or higher than a array of dimension 1 or 2?
不,一般情况下不会。 sum
等函数以与维度无关的方式实现需要引用.
Is there a clever way to replace a while loop that use the result of an iteration for the next iteration?
这在很大程度上取决于操作是什么。 cumsum
等函数通常可用于向量化此类代码,但并非总是如此。
这是我的计时代码,希望能说明如何正确使用timeit
:
%n = 10000;
n = 100;
Value = cumsum(ones(1,n));
vector1 = function01(n,Value);
vector2 = function02(n,Value);
vector3 = function03(n,Value);
vector4 = function04(n,Value);
assert(isequal(vector1,vector2))
assert(isequal(vector1,vector3))
assert(isequal(vector1,vector4))
timeit(@()function01(n,Value))
timeit(@()function02(n,Value))
timeit(@()function03(n,Value))
timeit(@()function04(n,Value))
function vector = function01(n,Value)
vector = zeros(2*n,1);
for k = 1:n
vector(2*k-1) = Value(k);
vector(2*k) = Value(k);
end
end
function vector = function02(n,Value)
vector = zeros(2*n,1);
vector(1:2:2*n) = Value;
vector(2:2:2*n) = Value;
end
function vector = function03(n,Value)
MatrixTmp = transpose([Value(:), Value(:)]);
vector = MatrixTmp(:);
end
function vector = function04(n,Value)
vector = [Value(:).'; Value(:).'];
vector = vector(:);
end
在 Matlab 中,我正在尝试矢量化我的代码以缩短模拟时间。然而,我得到的结果是我降低了整体效率。
为了理解这个现象,我创建了 3 个不同的函数,它们做同样的事情但方法不同:
主文件:
clc,
clear,
n = 10000;
Value = cumsum(ones(1,n));
NbLoop = 10000;
time01 = zeros(1,NbLoop);
time02 = zeros(1,NbLoop);
time03 = zeros(1,NbLoop);
for test = 1 : NbLoop
tic
vector1 = function01(n,Value);
time01(test) = toc ;
tic
vector2 = function02(n,Value);
time02(test) = toc ;
tic
vector3 = function03(n,Value);
time03(test) = toc ;
end
figure(1)
hold on
plot( time01, 'b')
plot( time02, 'g')
plot( time03, 'r')
函数 01:
function vector = function01(n,Value)
vector = zeros( 2*n,1);
for k = 1:n
vector(2*k -1) = Value(k);
vector(2*k) = Value(k);
end
end
函数 02:
function vector = function02(n,Value)
vector = zeros( 2*n,1);
vector(1:2:2*n) = Value;
vector(2:2:2*n) = Value;
end
函数 03:
function vector = function03(n,Value)
MatrixTmp = transpose([Value(:), Value(:)]);
vector = MatrixTmp (:);
end
蓝色图对应于 for - 循环。
n = 100:
n = 10000:
当我运行带有n = 100
的代码时,更有效的解决方案是第一个带有for循环的函数。
当 n = 10000
第一个函数变得效率较低。
- 您是否有办法知道如何以及何时将 for 循环正确地替换为向量化对应项?
- 使用超大维度数组进行索引搜索有何影响?
- Matlab 计算 3 维或更高维数组的方式是否与 1 维或 2 维数组不同?
- 有没有聪明的方法来替换使用迭代结果进行下一次迭代的 while 循环?
使用 MATLAB Online 我看到了不同的东西:
n 10000 100
function01 5.6248e-05 2.2246e-06
function02 1.7748e-05 1.9491e-06
function03 2.7748e-05 1.2278e-06
function04 1.1056e-05 7.3390e-07 (my version, see below)
因此,循环版本总是最慢的。方法 #2 对于非常大的矩阵更快,方法 #3 对于非常小的矩阵更快。
原因是方法#3 制作了 2 个数据副本(transpose
或一个矩阵产生了一个副本),如果数据很多,那就不好了。方法#2 使用索引,这很昂贵,但不如将大量数据复制两次那么昂贵。
我建议改为使用此函数(方法 #4),它仅转置向量(本质上是免费的)。这是对方法#3 的简单修改:
function vector = function04(n,Value)
vector = [Value(:).'; Value(:).'];
vector = vector(:);
end
Do you have a way to know how and when to properly replace a for-loop by a vectorised counterpart?
一般来说,矢量化代码总是更快如果没有大的中间矩阵。对于小数据,您可以更积极地进行向量化,对于大数据,有时由于内存压力降低,循环更有效。这取决于矢量化需要什么。
What is the impact of index searching with array of tremendous dimensions?
这里指的是d = data(data==0)
等操作。就像其他一切一样,这对小数据很有效,而对大数据则不太有效,因为 data==0
是一个与 data
.
Does Matlab compute in a different manner an array of dimensions 3 or higher than a array of dimension 1 or 2?
不,一般情况下不会。 sum
等函数以与维度无关的方式实现需要引用.
Is there a clever way to replace a while loop that use the result of an iteration for the next iteration?
这在很大程度上取决于操作是什么。 cumsum
等函数通常可用于向量化此类代码,但并非总是如此。
这是我的计时代码,希望能说明如何正确使用timeit
:
%n = 10000;
n = 100;
Value = cumsum(ones(1,n));
vector1 = function01(n,Value);
vector2 = function02(n,Value);
vector3 = function03(n,Value);
vector4 = function04(n,Value);
assert(isequal(vector1,vector2))
assert(isequal(vector1,vector3))
assert(isequal(vector1,vector4))
timeit(@()function01(n,Value))
timeit(@()function02(n,Value))
timeit(@()function03(n,Value))
timeit(@()function04(n,Value))
function vector = function01(n,Value)
vector = zeros(2*n,1);
for k = 1:n
vector(2*k-1) = Value(k);
vector(2*k) = Value(k);
end
end
function vector = function02(n,Value)
vector = zeros(2*n,1);
vector(1:2:2*n) = Value;
vector(2:2:2*n) = Value;
end
function vector = function03(n,Value)
MatrixTmp = transpose([Value(:), Value(:)]);
vector = MatrixTmp(:);
end
function vector = function04(n,Value)
vector = [Value(:).'; Value(:).'];
vector = vector(:);
end