简体   繁体   English

Python 基于瓦片的 numpy 数组处理

[英]Python tile based processing of numpy array

I have a very large numpy array of size [256,256,256,256] which takes up about 8GB of ram.我有一个非常大的 numpy 数组,大小为 [256,256,256,256],占用大约 8GB 内存。

I want to process the data quickly using multiprocessing, similar to the method used by tile based rendering software such as blender.我想使用多处理快速处理数据,类似于基于图块的渲染软件(如搅拌机)使用的方法。

I would like to split my data into chunks of smaller size, create a list of processes for them and when one finishes, start working on the next.我想将我的数据分成更小的块,为它们创建一个进程列表,当一个完成时,开始处理下一个。 My current method uses a V split, which is then looped over to perform hsplit and get the chunks.我当前的方法使用 V 拆分,然后循环执行 hsplit 并获取块。 Here is an example of the code for a much smaller data set (9 by 9 divided into 3 by 3 chunks):这是一个小得多的数据集的代码示例(9 x 9 分为 3 x 3 块):

import numpy as np

data = np.array(np.arange(0,81)).reshape((9,9))

print(data.shape)
print(data)
print("#"*30)
data = np.array([np.vsplit(set,3) for set in np.hsplit(data,3)])
print(data.shape)
print(data)
print("#"*30)

this doesn't quite do what I want it to, which is creating 9 chunks of 3 by 3 but that's a minor issue.这并不完全符合我的要求,即创建 9 个 3 x 3 的块,但这是一个小问题。 The major issue is I don't think looping through an array like that to apply vsplit is very efficient, but I'm not aware of a built in function that does this automatically without looping.主要问题是我不认为循环通过这样的数组来应用 vsplit 非常有效,但我不知道内置的 function 会自动执行此操作而无需循环。

I tried using map to see if it automatically applies vsplit in a more efficient way, but the timing results were very similar, so I don't think that's the case.我尝试使用 map 来查看它是否以更有效的方式自动应用 vsplit,但时序结果非常相似,所以我认为情况并非如此。 Any suggestions on how to optimize this problem?有关如何优化此问题的任何建议?

You want something as_strided based.你想要一些基于as_strided的东西。 I'd recommend my recipe here .我会在这里推荐我的食谱 Using this you can do:使用它,您可以执行以下操作:

patches = window_nd(data, window = 3, steps = 3)

To pass to multiprocessing, you'll need a generator.要传递到多处理,您需要一个生成器。 Something like:就像是:

def patch_gen(data, window, **kwargs):
    dims = len(data.shape)
    patches = window_nd(data, window, **kwargs)
    patches = patches.reshape((-1,) + patches.shape[-dims:])
    for i in range(patches.shape[0]):
        yield patches[i]

You can also use view_as_blocks as from @NilsWerner:您还可以使用来自view_as_blocks的 view_as_blocks:

def patch_gen(data, window_shape):
    dims = len(data.shape)
    patches = skimage.util.view_as_blocks(data, window_shape)
    patches = patches.reshape((-1,) + patches.shape[-dims:])
    for i in range(patches.shape[0]):
        yield patches[i]

Then you can do something like:然后您可以执行以下操作:

with Pool(processors) as p:
    out = p.map(func, patch_gen(data, window = 3, steps = 3))

This method should only use the original memory of the array and not make a copy at any point (I think).这种方法应该只使用数组的原始 memory 而不是在任何时候复制(我认为)。 That way you don't waste time and memory making copies of the original data, all the results are just pointers to the original data.这样您就不会浪费时间和 memory 复制原始数据,所有结果都只是指向原始数据的指针。

Caution: don't write to the patches, At least, in general it's a bad idea to write to as_strided results.注意:不要写补丁,至少, 一般来说写as_strided结果是个坏主意。 If you don't have overlapping windows you might be ok, but as soon as your windows overlap (ie steps < window ) you'll have a mess on your hands.如果你没有重叠的 windows 你可能没问题,但是一旦你的 windows 重叠(即steps < window )你的手就会一团糟

You can use SciKit-Image's skimage.util.view_as_blocks() , which solves your blocking problem without moving or copying any of the data.您可以使用SciKit-Image 的skimage.util.view_as_blocks() ,它可以在不移动或复制任何数据的情况下解决您的阻塞问题。

skimage.util.view_as_blocks(data, (3, 3))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM