为什么numpy数组元素的随机写入比随机读取慢很多?

问题描述 投票:1回答:1

下面的代码是一个图像二值化算法的一部分。我试图提高这个算法的性能,但我发现瓶颈在一个奇怪的地方。(算法中无关紧要的部分被省略了。)

@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管道中,有多个图像操作,所以我希望尽可能地优化每个操作。这种二值化是在每张图像上完成的,所以我想把运行时间降到几微秒。

python numpy numba
1个回答
0
投票

我想你可以用这个替换你的代码。

def make_buckets(img):
    return np.bincount(img.reshape(-1), minlength=256)

请试一试,然后告诉我们时间。

参考。https:/numpy.orgdocstablereferencegeneratednumpy.bincount.html。

© www.soinside.com 2019 - 2024. All rights reserved.