Это связано с этим вопросом
Я хочу знать, как вычислить медианное значение по указанному c измерению на огромном массиве, например, с размером (20, 1920, 1080, 3 ). Я не уверен, есть ли в этом какая-то практическая цель, но я просто хотел проверить, насколько хорошо работает медиана в Julia.
Для вычисления медианы на (3,1920,1080) требуется ~ 0,5 секунды с. , 3) с numpy. Он работает очень быстро с массивом нулей (менее 2 секунд на (120, 1920, 1080,3)) и работает не так быстро, но отлично на реальных изображениях (20 секунд на (120, 1920, 1080,3)).
Python код:
import cv2
import sys
import numpy as np
import time
ZEROES=True
N_IMGS=20
print("n_imgs:", N_IMGS)
print("use dummy data:", ZEROES)
imgs_paths = sys.argv[1:]
imgs_paths.sort()
imgs_paths_sparse = imgs_paths[::30]
imgs_paths = imgs_paths_sparse[N_IMGS]
if ZEROES:
imgs_arr = np.zeros((N_IMGS,1080,1920,3), dtype=np.float32)
else:
imgs = map(cv2.imread, imgs_paths)
imgs_arr = np.array(list(imgs), dtype=np.float32)
start = time.time()
imgs_median = np.median(imgs_arr, 0)
end = time.time()
print("time:", end - start)
cv2.imwrite('/tmp/median.png', imgs_median)
В julia я могу вычислить только медианное значение (3, 1920, 1080,3). После этого мой процесс earlyoom
убивает процесс julia из-за огромного количества используемой памяти.
Я пробовал подход, аналогичный тому, который я пробовал сначала на max
:
function median1(imgs_arr)
a = imgs_arr
b = reshape(cat(a..., dims=1), tuple(length(a), size(a[1])...))
imgs_max = Statistics.median(b, dims=1)
return imgs_max
end
Или даже больше простой случай:
import Statistics
a = zeros(3,1080,1920,3)
@time Statistics.median(a, dims=1)
10.609627 seconds (102.64 M allocations: 2.511 GiB, 3.37% gc time)
...
Итак, это занимает 10 секунд против 0,5 секунды на numpy. У меня всего 4 ядра процессора и это не просто распараллеливание.
Есть более-менее простой способ как-то оптимизировать?
Или, по крайней мере, взять срезы и вычислить их один за другим без чрезмерного использования памяти?