下面的代码是一个图像二值化算法的一部分。我试图提高这个算法的性能,但我发现瓶颈在一个奇怪的地方。(算法中无关紧要的部分被省略了。)
@jit(nopython=True)
def make_buckets(img):
height, width = img.shape
buckets = np.zeros(256)
# buckets = np.full(256, 0) [I tried both, sometimes one works better than other]
for h in range(height):
for w in range(width):
g = img[h, w]
a = buckets[g] + 1
# buckets[g] = 1
# buckets[g] = a
img = np.random.randint(0, 256, (224, 224))
%timeit make_buckets(img)
上述代码的运行时间为。
539 ns ± 12.2 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
这是很好的。这意味着,获取访问 buckets[g]
在一个循环里面,根本没有要求。让我们看看如果我取消这一行会发生什么。buckets[g] = 1
for h in range(height):
for w in range(width):
g = img[h, w]
a = buckets[g] + 1
buckets[g] = 1
# buckets[g] = a
运行时是:
27.8 µs ± 865 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
这意味着设置 buckets[g]
内的循环会大大增加运行时间。
现在,如果我取消对 buckets[g] = a
这样的行。
for h in range(height):
for w in range(width):
g = img[h, w]
a = buckets[g] + 1
# buckets[g] = 1
buckets[g] = a
运行时间增加到:
37.8 µs ± 1.09 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
这个运行时间的增量是一致的,并且取决于... ... img
矩阵,可能需要>100 µs。这也意味着将矩阵元素设置为变量比设置为常量要慢得多。谁能解释一下,为什么在循环中把矩阵元素设置为变量会大大增加运行时间?另外,你能建议fs有什么办法比这更提高性能吗?
我正在对数百万张图片(手写文档)进行机器学习,所以我的数据生成器应该足够快,这样才不会让GPU出现瓶颈。在datagenerator管道中,有多个图像操作,所以我希望尽可能地优化每个操作。这种二值化是在每张图像上完成的,所以我想把运行时间降到几微秒。
我想你可以用这个替换你的代码。
def make_buckets(img):
return np.bincount(img.reshape(-1), minlength=256)
请试一试,然后告诉我们时间。
参考。https:/numpy.orgdocstablereferencegeneratednumpy.bincount.html。