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

时间:2020-05-03 00:54:30

标签: python numpy numba

以下代码是图像二值化算法的一部分。我正在尝试提高该算法的性能,但发现瓶颈在一个陌生的地方。 (算法的低等部分被省略。)

@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的瓶颈。在数据生成器管道中,有多种图像操作,因此我想尽可能地优化每个操作。在每个图像上都进行了二值化,因此我想将运行时间缩短到几微秒。

1 个答案:

答案 0 :(得分:0)

我认为您可以用以下代码替换代码:

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

请尝试一下,让我们知道时间。

参考:https://numpy.org/doc/stable/reference/generated/numpy.bincount.html