测试这些东西对你有好处。但是,您需要学习如何进行这些测试以获得良好的信息。
首先,花费的时间非常少,所以重复测试总是最好的。其次,使用类似timeit的工具。它为您完成所有工作,消除了许多错误来源,尽管它需要将其目标封装为一个函数。
接下来,存在与 TINY 问题有关的问题。你的测试用例很小。事实上,代码花费时间的原因有很多。考虑功能开销和启动成本。调用函数需要时间,因为设置和销毁函数工作区会产生开销。此外,GOOD 函数将进行错误测试,并提供多个选项。但要做到这一点,它必须检查是否设置了这些选项。因此花费了时间,通常没有做任何有价值的事情,因为您只想以某种简单的形式使用该功能。这意味着当你调用函数来向量化一个微小的计算时,它实际上可能比你只使用内联的非向量化形式花费更多的时间。所以小的测试用例往往会产生误导。(我打算为更大的问题添加时间比较,但到那时 Marc 已经在他的回答中这样做了。
您还应该学习使用 bsxfun,这是一种旨在优化您正在测试的表单的某些计算的工具。同样,小问题通常不会显示出太多的速度提升(如果有的话)。
接下来,JIT 存在问题,MATLAB 中用于优化一些简单代码的加速。如果那个(对你不可见的)工具能够很好地处理你正在测试的代码,那么它看起来好像循环更快。
做一些测试是好的,所以让我们做一个比较。由于您的示例都主要是内联的,因此我将在每个案例周围放置一个大循环。这将减少测试错误的主要来源之一。
Ktot = 100;
N = 10;
Initial = [zeros(N,1) ones(N,1)];
tic
for k = 1:Ktot
for xpop=1:N
for nvar=1:N
Parent(xpop,nvar) = Initial(nvar,1)+(Initial(nvar,2)-Initial(nvar,1))*rand();
end
end
end
toc
tic
for k = 1:Ktot
Parent = repmat(Initial(:,1),1,N) + rand(N,N).*(repmat(Initial(:,2),1,N)-repmat(Initial(:,1),1,N));
end
toc
你能改进你的矢量化形式吗?为什么两个 repmats,一个也可以工作?
tic
for k = 1:Ktot
Parent = repmat(Initial(:,1),1,N) + rand(N,N).*repmat(Initial(:,2)-Initial(:,1),1,N);
end
toc
bsxfun 呢?
tic
for k = 1:Ktot
Parent = bsxfun(@plus,Initial(:,1),bsxfun(@times,rand(N,N),Initial(:,2)-Initial(:,1)));
end
toc
因此,当 N = 10 和 Ktot = 100 时,我看到这样的时间:
Elapsed time is 0.003935 seconds.
Elapsed time is 0.012250 seconds.
Elapsed time is 0.008269 seconds.
Elapsed time is 0.004304 seconds.
同样,这是一个小问题。如果我们扩大问题会发生什么?尝试 N = 100,而不是 N = 10。
Elapsed time is 0.131186 seconds.
Elapsed time is 0.031671 seconds.
Elapsed time is 0.027205 seconds.
Elapsed time is 0.019763 seconds.
因此,我们看到事情的整理更加合乎逻辑。现在 bsxfun 变体开始显示出一些收益。接下来,上升到 N = 1000。
Elapsed time is 12.288608 seconds.
Elapsed time is 3.412531 seconds.
Elapsed time is 2.690691 seconds.
Elapsed time is 1.626599 seconds.
本质上,所有这些代码都做同样的工作,只是有些代码在构建问题的方式上更有效,而有些代码的开销更大。正如我们在更大的问题中看到的那样,显式循环变得平坦。