MATLAB的幂函数用于计算常数基和指数数组的元素取指数,当数组的大小变为512时,速度显着提高。我希望看到计算时间随输入大小而增加,但是当指数数组中有512个元素时,下降明显。这是示例代码
...\vendor\laravel\framework\src\Illuminate\Foundation\Auth\RedirectsUsers.php
代码的输出是
x_list = 510:514;
for i = 1:numel(x_list)
x = x_list(i);
tic
for j = 1:10000
y = power(2,1:x);
end
toc
end
这是怎么回事?
答案 0 :(得分:9)
使用指数随机数的效果相同,就像使用1:n
范围内的整数一样:
x = 500:540;
t = zeros(size(x));
for ii = 1:numel(x)
%m = 1:x(ii);
m = 500*rand(1,x(ii));
t(ii) = timeit(@()power(2,m));
end
plot(x,t)
当迫使MATLAB使用maxNumCompThreads(1)
的单个线程,并再次运行上面的代码时,我看到的是这张图(注意y轴,峰值只是噪声):
在我看来,MATLAB使用单个核来计算511个值的指数,并且如果矩阵较大,则会激发所有核。使用多线程会产生开销,对于小型数组而言,这样做是不值得的。通过节省时间来平衡开销的确切点取决于许多因素,因此,硬编码固定阈值以决定何时切换到多线程计算,会导致具有与系统特性不同的系统的执行时间增加。确定阈值。
请注意,由于@ norok2在其系统MATLAB was limited to a single thread上,因此没有看到相同的跳转。
答案 1 :(得分:4)
这与计算功率的数字大小有关,而不与容器的大小有关。
如果使用随机数,则对于不同的容器大小,不会在时间上出现跳跃:
x = 450:1550;
y = zeros(numel(x), 1);
X = rand(1, 10000);
for i = 1:length(x)
f = @() 2 .^ X(1:x(i));
y(i) = timeit(f);
end
figure()
plot(x, y)
因此,问题必须出在很大数字的计算上。
首先,我认为这可能与溢出有关,但是溢出发生在2 ^ 1024 == inf
上,这是MATLAB遵循的IEEE standards所决定的,我认为对于inf
比计算一个实数快得多。
以下基准测试支持这一点,其中数组的大小保持不变:
x = 450:1550;
y = zeros(numel(x), 1);
X = rand(1, 10000);
for i = 1:length(x)
f = @() 2 .^ (ones(1, 500) * x(i));
y(i) = timeit(f);
end
figure()
plot(x, y)
当我不了解2 ^ 512
而不是2 ^ 1024
时,为什么这可能与您的设置有关?
(请注意,我使用的是2 .^ ...
而不是power(2, ...)
,但结果是相同的。)
此外,在我的系统中运行@CrisLuengo的代码并不会真正产生任何跳转。
x = 500:540;
t = zeros(size(x));
for ii = 1:numel(x)
%m = 1:x(ii);
m = 500*rand(1,x(ii));
t(ii) = timeit(@()power(2,m));
end
plot(x,t)
到目前为止,所有证据表明峰值与JIT延迟/预热有关。
答案 2 :(得分:4)
以下是使用运行MATLAB R2018a的4核Windows机器对Cris found进行的确认。我首先测试了以下代码,以表明指数的特定值不是跳转的罪魁祸首:
t = zeros(4, 1000);
for p = 1:size(t, 1)
for n = 1:size(t, 2)
t(p, n) = timeit(@() power(2, (2.^(p-1)).*ones(1, n)));
end
end
结果如下:
对于退化边缘情况,指数为1(返回相同的值)或2(返回值乘以自身),计算将按预期运行。但是,与数组大小超过512时指数为4和8的计算时间减少相比,在数组大小为512或更大的情况下跳转表明增加到这些边缘情况。值只是复制上面的曲线。
然后我又进行了两个测试:一个数组大小在1到511之间,第二个数组大小在512到1024之间。这是处理器负载的样子:
处理器3在第一次测试期间显示出很大的负载峰值,而所有4个处理器在第二次测试期间显示出了负载峰值。这证实了多线程用于512或更大的数组大小。这也解释了对于大尺寸边缘情况的计算较慢,因为多线程的开销超过了通过拆分较简单的计算所提供的加速。