求和矩阵元素的最快方法
Fastest way to sum the elements of a matrix
我的代码效率有一些问题。基本上我的代码是这样工作的:
a = zeros(1,50000);
for n = 1:50000
a(n) = 10.*n - 5;
end
sum(a);
求解该矩阵所有元素之和的最快方法是什么?
首先,您想通过将其设为向量乘法来删除 for 循环:
tic
a = zeros(1,50000);
b = [1:50000];
a = 10.*b-5;
result = sum(a);
toc
Elapsed time is 0.008504 seconds.
另一种方法是简化您的操作,您将 1 到 50000 乘以 10 并减去 5,然后求和(这是一个单一的数字),这相当于:
tic
result = sum(1:50000)*10 - 5*50000;
toc
Elapsed time is 0.003851 seconds.
或者如果你真的很喜欢数学(这是一种纯数学表达式方法):
tic
result = (1+50000)*(50000/2)*10 - 5*50000;
toc
Elapsed time is 0.003702 seconds.
正如您所看到的,一点数学可以比纯粹的高效编程做得更好,实际上,循环并不总是很慢,在您的情况下,循环实际上比向量化方法更快:
tic
a = zeros(1,50000);
for n = 1:50000
a(n)=10.*n-5;
end
sum(a);
toc
Elapsed time is 0.006431 seconds.
时机
让我们做一些计时,看看结果。 运行它自己的功能在底部提供。近似执行时间 execTime
以秒为单位,改进百分比 impPercentage
以 % 为单位。
结果
R2016a OSX 10.11.4
execTime impPercentage
__________ _____________
loop 0.00059336 0
vectorized 0.00014494 75.574
adiel 0.00010468 82.359
math 9.3659e-08 99.984
代码
以下函数可用于生成输出。请注意,它至少需要 R2013b 才能使用内置 timeit
函数和 table
.
function timings
%feature('accel','on') %// commented out because it's undocumented
cycleCount = 100;
execTime = zeros(4,cycleCount);
names = {'loop';'vectorized';'adiel';'math'};
w = warning;
warning('off','MATLAB:timeit:HighOverhead');
for k = 1:cycleCount
execTime(1,k) = timeit(@()loop,1);
execTime(2,k) = timeit(@()vectorized,1);
execTime(3,k) = timeit(@()adiel,1);
execTime(4,k) = timeit(@()math,1);
end
warning(w);
execTime = min(execTime,[],2);
impPercentage = (1 - execTime/max(execTime)) * 100;
table(execTime,impPercentage,'RowNames',names)
function result = loop
a = zeros(1,50000);
for n = 1:50000
a(n) = 10.*n - 5;
end
result = sum(a);
function result = vectorized
b = 1:50000;
a = 10.*b - 5;
result = sum(a);
function result = adiel
result = sum(1:50000)*10 - 5*50000;
function result = math
result = (1+50000)*(50000/2)*10 - 5*50000;
我的代码效率有一些问题。基本上我的代码是这样工作的:
a = zeros(1,50000);
for n = 1:50000
a(n) = 10.*n - 5;
end
sum(a);
求解该矩阵所有元素之和的最快方法是什么?
首先,您想通过将其设为向量乘法来删除 for 循环:
tic
a = zeros(1,50000);
b = [1:50000];
a = 10.*b-5;
result = sum(a);
toc
Elapsed time is 0.008504 seconds.
另一种方法是简化您的操作,您将 1 到 50000 乘以 10 并减去 5,然后求和(这是一个单一的数字),这相当于:
tic
result = sum(1:50000)*10 - 5*50000;
toc
Elapsed time is 0.003851 seconds.
或者如果你真的很喜欢数学(这是一种纯数学表达式方法):
tic
result = (1+50000)*(50000/2)*10 - 5*50000;
toc
Elapsed time is 0.003702 seconds.
正如您所看到的,一点数学可以比纯粹的高效编程做得更好,实际上,循环并不总是很慢,在您的情况下,循环实际上比向量化方法更快:
tic
a = zeros(1,50000);
for n = 1:50000
a(n)=10.*n-5;
end
sum(a);
toc
Elapsed time is 0.006431 seconds.
时机
让我们做一些计时,看看结果。 运行它自己的功能在底部提供。近似执行时间 execTime
以秒为单位,改进百分比 impPercentage
以 % 为单位。
结果
R2016a OSX 10.11.4
execTime impPercentage __________ _____________ loop 0.00059336 0 vectorized 0.00014494 75.574 adiel 0.00010468 82.359 math 9.3659e-08 99.984
代码
以下函数可用于生成输出。请注意,它至少需要 R2013b 才能使用内置 timeit
函数和 table
.
function timings
%feature('accel','on') %// commented out because it's undocumented
cycleCount = 100;
execTime = zeros(4,cycleCount);
names = {'loop';'vectorized';'adiel';'math'};
w = warning;
warning('off','MATLAB:timeit:HighOverhead');
for k = 1:cycleCount
execTime(1,k) = timeit(@()loop,1);
execTime(2,k) = timeit(@()vectorized,1);
execTime(3,k) = timeit(@()adiel,1);
execTime(4,k) = timeit(@()math,1);
end
warning(w);
execTime = min(execTime,[],2);
impPercentage = (1 - execTime/max(execTime)) * 100;
table(execTime,impPercentage,'RowNames',names)
function result = loop
a = zeros(1,50000);
for n = 1:50000
a(n) = 10.*n - 5;
end
result = sum(a);
function result = vectorized
b = 1:50000;
a = 10.*b - 5;
result = sum(a);
function result = adiel
result = sum(1:50000)*10 - 5*50000;
function result = math
result = (1+50000)*(50000/2)*10 - 5*50000;