Следующий код является частью алгоритма бинаризации изображения. Я пытаюсь улучшить производительность этого алгоритма, но я нахожу узкое место в странном месте. (Нерелевантные части алгоритма опущены.)
@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]
внутри al oop совсем не требователен. Давайте посмотрим, что произойдет, если я раскомментирую эту строку: 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]
внутри al oop значительно увеличивает время выполнения.
Теперь, если я раскомментирую строку 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 мкс. Это также означает, что установка элемента матрицы в переменную намного медленнее, чем установка его в константу. Может кто-нибудь объяснить, почему установка элемента матрицы в переменную al oop так сильно увеличивает время выполнения? Кроме того, можете ли вы предположить, что есть какой-то способ улучшить производительность, чем этот?
Я занимаюсь машинным обучением с миллионами изображений (рукописных документов), поэтому мой генератор данных должен быть достаточно быстрым, чтобы это не узкое место GPU. В конвейере генератора данных происходит множество манипуляций с изображениями, поэтому я хочу максимально оптимизировать каждую операцию. Эта бинаризация выполняется для каждого изображения, поэтому я хочу сократить время выполнения до нескольких микросекунд.