`eval` 与 `str2func` 相比从字符串评估函数的性能
Performance of `eval` compared to `str2func` to evalulate a function from a string
eval
and str2func
都能够计算由字符串 f.e 表示的函数。 f='a^x+exp(b)+sin(c*x)+d'
:
使用eval
:
y = eval(f)
或(rahnema1 建议)
fHandle = eval(['@(x, a, b, c, d) ' f]);
y = fHandle(x, a, b, c, d);
使用str2func
:
fHandle = str2func(['@(x, a, b, c, d) ' f]);
y = fHandle(x, a, b, c, d);
两种方法中哪种方法的性能最好?
备注
请注意,此基准测试的灵感来自 。
简答:使用str2func
。
基准
基准测试将针对 N
个不同的 x
值评估函数。
f='a^x+exp(b)+sin(c*x)+d';
Ns = linspace(1, 1000, 20);
timeEval = zeros(size(Ns));
timeEvalHandle = zeros(size(Ns));
timeStr2func = zeros(size(Ns));
for i=1:length(Ns)
N = Ns(i);
timeEval(i) = timeit(@() useEval(f, N));
timeEvalHandle(i) = timeit(@() useEvalHandle(f, N));
timeStr2func(i) = timeit(@() useStr2func(f, N));
end
figure
plot(Ns, timeEval, 'DisplayName', 'time eval');
hold on
plot(Ns, timeEvalHandle, 'DisplayName', 'time eval');
hold on
plot(Ns, timeStr2func, 'DisplayName', 'time str2func');
legend show
xlabel('N');
figure
plot(Ns, timeEval./timeStr2func, 'DisplayName', 'time_{eval}/time_{str2func}');
hold on
plot(Ns, timeEvalHandle./timeStr2func, 'DisplayName', 'time_{eval handle}/time_{str2func}');
legend show
xlabel('N');
figure
plot(Ns, timeEvalHandle./timeStr2func);
ylabel('time_{eval handle}/time_{str2func}')
xlabel('N');
function y = useEval(f, N)
a = 1; b = 2; c = 3; d = 4;
for x=1:N
y = eval(f);
end
end
function y = useEvalHandle(f, N)
a = 1; b = 2; c = 3; d = 4;
fHandle = eval(['@(x, a, b, c, d) ' f]);
for x=1:N
y = fHandle(x, a, b, c, d);
end
end
function y = useStr2func(f, N)
a = 1; b = 2; c = 3; d = 4;
fHandle = str2func(['@(x, a, b, c, d) ' f]);
for x=1:N
y = fHandle(x, a, b, c, d);
end
end
str2func
vs eval
(没有函数句柄): 结果表明,即使对函数求值一次,它的速度也快了大约 50%使用 str2func
而不是 eval
(没有函数句柄)。对于大量评估,str2func
可能快 100 倍左右(取决于您评估的函数)。
str2func
vs eval
(带函数句柄): eval
比 str2func
慢 100% 左右单个评估,但对于大量评估来说变得几乎同样快(eval
慢 ~5%)。
eval
带和不带函数句柄: 请注意,对于单个评估,使用 eval
创建函数句柄比评估它慢 ~50%直接。
结论: str2func
总是比eval
快。
在以下基准测试中,创建了一个函数句柄集合,并将 eval
的性能与 str2func
的性能进行比较以评估字符串。这些函数是变量与 +- 符号的组合。
n = 16;
op=char((dec2bin(0:2^n-1)-48)*2+43);
vars= 'a':'z';
v = vars(1:n+1);
s(1:2^n,1:2:2*n+1)=repmat(v,2^n,1);
s(:,2:2:end)=op;
h=repmat(['@(' sprintf('%c,',v(1:end-1)) v(end) ')'],2^n,1);
farray=[h,s];
tic
for k = 1:2^n
f = eval(farray(k,:));
end
toc
tic
for k = 1:2^n
f = str2func(farray(k,:));
end
toc
八度结果:
两种方法没有区别。
eval
and str2func
都能够计算由字符串 f.e 表示的函数。 f='a^x+exp(b)+sin(c*x)+d'
:
使用
eval
:y = eval(f)
或(rahnema1 建议)
fHandle = eval(['@(x, a, b, c, d) ' f]); y = fHandle(x, a, b, c, d);
使用
str2func
:fHandle = str2func(['@(x, a, b, c, d) ' f]); y = fHandle(x, a, b, c, d);
两种方法中哪种方法的性能最好?
备注
请注意,此基准测试的灵感来自
简答:使用str2func
。
基准
基准测试将针对 N
个不同的 x
值评估函数。
f='a^x+exp(b)+sin(c*x)+d';
Ns = linspace(1, 1000, 20);
timeEval = zeros(size(Ns));
timeEvalHandle = zeros(size(Ns));
timeStr2func = zeros(size(Ns));
for i=1:length(Ns)
N = Ns(i);
timeEval(i) = timeit(@() useEval(f, N));
timeEvalHandle(i) = timeit(@() useEvalHandle(f, N));
timeStr2func(i) = timeit(@() useStr2func(f, N));
end
figure
plot(Ns, timeEval, 'DisplayName', 'time eval');
hold on
plot(Ns, timeEvalHandle, 'DisplayName', 'time eval');
hold on
plot(Ns, timeStr2func, 'DisplayName', 'time str2func');
legend show
xlabel('N');
figure
plot(Ns, timeEval./timeStr2func, 'DisplayName', 'time_{eval}/time_{str2func}');
hold on
plot(Ns, timeEvalHandle./timeStr2func, 'DisplayName', 'time_{eval handle}/time_{str2func}');
legend show
xlabel('N');
figure
plot(Ns, timeEvalHandle./timeStr2func);
ylabel('time_{eval handle}/time_{str2func}')
xlabel('N');
function y = useEval(f, N)
a = 1; b = 2; c = 3; d = 4;
for x=1:N
y = eval(f);
end
end
function y = useEvalHandle(f, N)
a = 1; b = 2; c = 3; d = 4;
fHandle = eval(['@(x, a, b, c, d) ' f]);
for x=1:N
y = fHandle(x, a, b, c, d);
end
end
function y = useStr2func(f, N)
a = 1; b = 2; c = 3; d = 4;
fHandle = str2func(['@(x, a, b, c, d) ' f]);
for x=1:N
y = fHandle(x, a, b, c, d);
end
end
str2func
vs eval
(没有函数句柄): 结果表明,即使对函数求值一次,它的速度也快了大约 50%使用 str2func
而不是 eval
(没有函数句柄)。对于大量评估,str2func
可能快 100 倍左右(取决于您评估的函数)。
str2func
vs eval
(带函数句柄): eval
比 str2func
慢 100% 左右单个评估,但对于大量评估来说变得几乎同样快(eval
慢 ~5%)。
eval
带和不带函数句柄: 请注意,对于单个评估,使用 eval
创建函数句柄比评估它慢 ~50%直接。
结论: str2func
总是比eval
快。
在以下基准测试中,创建了一个函数句柄集合,并将 eval
的性能与 str2func
的性能进行比较以评估字符串。这些函数是变量与 +- 符号的组合。
n = 16;
op=char((dec2bin(0:2^n-1)-48)*2+43);
vars= 'a':'z';
v = vars(1:n+1);
s(1:2^n,1:2:2*n+1)=repmat(v,2^n,1);
s(:,2:2:end)=op;
h=repmat(['@(' sprintf('%c,',v(1:end-1)) v(end) ')'],2^n,1);
farray=[h,s];
tic
for k = 1:2^n
f = eval(farray(k,:));
end
toc
tic
for k = 1:2^n
f = str2func(farray(k,:));
end
toc
八度结果:
两种方法没有区别。