【发布时间】:2020-09-14 06:08:46
【问题描述】:
我想知道如何沿巨大数组的特定维度计算中位数,例如大小为 (20, 1920, 1080, 3)。我不确定是否有任何实际用途,但我只是想检查一下中位数在 Julia 中的工作情况。
使用 numpy 计算 (3,1920,1080,3) 上的中位数需要 ~0.5 秒s。它在 zeros 数组上工作得非常快(在 (120, 1920, 1080,3) 上不到 2 秒),在真实图像上工作得不是那么快但很好(在 (120, 1920, 1080,3) 上 20 秒)。
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)
...
因此,在 numpy 上需要 10 秒,而 0.5 秒。 我只有 4 个 CPU 内核,这不仅仅是并行化。
是否有或多或少简单的方法来优化它?
或者至少在不过度使用内存的情况下进行切片并逐个计算?
【问题讨论】:
-
如果您在 Julia 中而不是仅在 Python 中设置问题,那么 Julia 人员会更容易提供帮助——很难知道 Julia 中的等效设置是什么。例如,Fredrik 的回答为所有图像使用了一个连续的块,这似乎忽略了单独加载图像的关键问题。不过,考虑到提出问题的方式,这似乎很公平,因为它并不具体。