[英]Optimizing array operations in Python with Numpy
我很困惑。 我只是将我的代码从Java移植到Python。 商品新闻是我使用的lib的Python替代品更快。 不好的是我的自定义处理代码比我写的Python替代要慢得多:(我甚至删除了一些我认为不必要的部分,仍然慢得多.Java版本花了大约半秒钟,Python需要5-6。
rimg1 = imageio.imread('test1.png').astype(np.uint8)
rimg2 = imageio.imread('test2.png').astype(np.uint8)
sum_time = 0
for offset in range(-left, right):
rdest = np.zeros((h, w, 3)).astype(np.uint8)
if offset == 0:
continue
mult = np.uint8(1.0 / (offset * multiplier / frames))
for y in range(h):
for x in range(0, w - backup, 1):
slice_time = time.time()
src = rimg2[y,x] // mult + 1
sum_time += time.time() - slice_time
pix = rimg1[y,x + backup]
w~ = 384和h~ = 384 src通常为0-30。 从左到右是-5到5
sum_time怎么花费我总时间的三分之一?
编辑
在josephjscheidt的帮助下,我做了一些改变。
mult = np.uint8(1.0 / (offset * multiplier / frames))
multArray = np.floor_divide(rimg2, mult) + 1
for y in range(h):
pixy = rimg1[y]
multy = multArray[y]
for x in range(0, w - backup, 1):
src = multy[y]
slice_time = time.time()
pix = pixy[x + backup]
sum_time += time.time() - slice_time
ox = x
for o in range(src):
if ox < 0:
break
rdest[y,ox] = pix
ox-=1
使用srcArray的numpy迭代器将总时间减少了近一半! numpy操作本身似乎花费的时间可以忽略不计。
现在大部分时间都是在rimg1查找中
pix = rimg1[x + backup]
内部for循环(两者占用50%的时间)。 是否有可能通过numpy操作来处理这个问题?
编辑
我想重写它可能是有益的,但不知何故,以下实际上需要更长一点:
for x in range(0, w - backup, 1):
slice_time = time.time()
lastox = max(x-multy[y], 0)
rdest[y,lastox:x] = pixy[x + backup]
sum_time += time.time() - slice_time
编辑
slice_time = time.time()
depth = multy[y]
pix = pixy[x + backup]
ox = x
#for o in range(depth):
# if ox < 0:
# break;
#
# rdesty[ox] = pix
# ox-=1
# if I uncomment the above lines, and comment out the following two
# it takes twice as long!
lastox = max(x-multy[y], 0)
rdesty[lastox:x] = pixy[x + backup]
sum_time += time.time() - slice_time
python解释器很奇怪..
sum_time现在花费的时间是2.5秒。 相比之下,Java在60ms内完成
对于numpy数组而言,for循环非常慢,并且这里有一个三层for循环。 numpy数组的基本概念是一次对整个数组执行操作,而不是尝试迭代它们。
虽然我无法完全解释您的代码,因为大多数变量在您提供的代码块中未定义,我相当有信心您可以在这里重构并向量化您的命令以删除循环。 例如,如果将偏移重新定义为一维数组,则可以一次计算mult的所有值,而无需调用for循环:mult将成为保持正确值的一维数组。 我们可以使用out参数(将默认输出设置为偏移数组)和where参数(仅在offset不等于零的情况下执行计算)来避免除以零:
mult = np.uint8(np.divide(1.0, (offset * multiplier / frames),
out = offset, where = (offset != 0))
然后,要逐行使用rimg2上的mult数组,你可以使用广播技巧(这里,我假设你想在rimg2中为每个元素添加一个):
src = np.floor_divide(rimg2, mult[:,None], out = rimg2, where = (mult != 0)) + 1
在学习如何有效地使用numpy数组时,我发现这篇文章非常有用:
https://realpython.com/numpy-array-programming/
由于您正在处理图像,因此您可能需要特别注意有关图像特征提取和stride_tricks的部分。 无论如何,我希望这可以帮助你开始。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.