我对numpy和skimage中的某些操作的计时很感兴趣,但我偶尔会看到我的努力产生了奇怪的(不完全可复制的)结果。简单地说,有时timeit
返回的结果与看起来相同的操作相差大约5倍。以下是设置:
import skimage
import numpy as np
import timeit
nrep = 16
def run_complement(img):
def inner():
skimage.util.invert(img)
return inner
img = np.random.randint(0, 65535, (512, 512, 3), dtype='uint16')
下面是一个示例课程:
In [1]: %run python_timing_bug.py
In [2]: t = timeit.Timer(run_complement(img))
In [3]: t.repeat(nrep, number=1)
Out[3]:
[0.0024439050030196086,
0.0020311699918238446,
0.00033007100864779204,
0.0002889479947043583,
0.0002851780009223148,
0.0002851030003512278,
0.00028487699455581605,
0.00032116699730977416,
0.00030912700458429754,
0.0002877369988709688,
0.0002840430097421631,
0.00028515000303741544,
0.00030791999597568065,
0.00029302599432412535,
0.00030723700183443725,
0.0002916679950430989]
In [4]: t = timeit.Timer(run_complement(img))
In [5]: t.repeat(nrep, number=1)
Out[5]:
[0.0006320849934127182,
0.0004014919977635145,
0.00030359599622897804,
0.00029224599711596966,
0.0002907510061049834,
0.0002920039987657219,
0.0002918920072261244,
0.0003095199936069548,
0.00029789700056426227,
0.0002885590074583888,
0.00040198900387622416,
0.00037131100543774664,
0.00040271600300911814,
0.0003492849937174469,
0.0003378120018169284,
0.00029762100894004107]
In [6]: t = timeit.Timer(run_complement(img))
In [7]: t.repeat(nrep, number=1)
Out[7]:
[0.00026428700948599726,
0.00012682100350502878,
7.380900206044316e-05,
6.346100417431444e-05,
6.29679998382926e-05,
6.278700311668217e-05,
6.320899410638958e-05,
6.25409884378314e-05,
6.262199894990772e-05,
6.247499550227076e-05,
6.293901242315769e-05,
6.259800284169614e-05,
6.285199197009206e-05,
6.293600017670542e-05,
6.309800664894283e-05,
6.248900899663568e-05]
请注意,在最后一次运行中,最小时间约为0.6e-4,而之前的最小时间约为3e-4,比之前运行中测得的时间小约5倍。当这种情况发生时,并不完全可以预测
更快的时间对应于阵列的0.08ns/单元,考虑到我的i7-8850H CPU上的2.6GHz时钟每~0.4ns滴答一次,这似乎已经超出了可信性的极限(尽管多亏了SIMD,也许不能完全排除这种可能性)。我的理解是,这个操作是implemented as a subtraction,并且很可能被减少为按位操作,而不是由编译器进行。(因此,您确实希望这是快速的,但不能完全确定它应该是这快速的,并且在这两种情况下,不可再现性都是有问题的。)
可能需要注意的是,数据总量是
In [15]: img.size * 2
Out[15]: 1572864
和lshw
报告我有384KB的一级缓存和1536KB的二级缓存:
In [16]: 384*1024
Out[16]: 393216
In [17]: 1536*1024
Out[17]: 1572864
因此,这一结果似乎可能受到二级缓存拟合的影响。(请注意,超快运行发生在第一次运行之后。)如果我增加图像的大小:
img = np.random.randint(0, 65535, (2048, 2048, 3), dtype='uint16')
然后,我的结果看起来更具可复制性,并且与其他语言的结果更为一致,并快速实现了此操作
是否有人对正在发生的事情有更深的了解,以及如何最好地管理它
目前没有回答
相关问题 更多 >
编程相关推荐