如何并行写入 numpy 数组中的同一单元格?

How to parallelize writing to same cell in a numpy array?

背景:我在 2D space 中有数百万个点,每个点都与 (x_position, y_position, value) 相关联。我试图通过创建图像来总结这些点,其中每个像素可以包含多个点。总而言之,每个像素存储图像中 (x_pixel, y_pixel) 位置的 values 的总和。

问题:我怎样才能有效地做到这一点?目前,我的代码执行如下操作:

image = np.zeros((4096,4096))
for each point in data:
    x_pixel, y_pixel = convertPointPos2PixelPos(point)
    image[x_pixel, y_pixel] += point.getValue()

但是完成此代码的 ETA 是 450 小时,这是不可接受的。有没有办法并行化这个?代码多次写入同一个 image[x,y] 索引。我发现建议使用 multiprocessing 的 Whosebug 帖子,但我认为需要 lock 来防止竞争条件意味着这将花费与不并行化一样多的时间。

假设您想要规则网格上的内容,您可以使用简单的除法来对数据进行分类。这是一个例子:

size = (4096, 4096)
data = np.random.rand(100000000, 3)
image = np.zeros(size)

coords = data[:, :2]
min = coords.min(0)
max = coords.max(0)

index = np.floor_divide(coords - min, (max - min) / np.subtract(size, 1), out=np.empty(coords.shape, dtype=int), casting='unsafe')

index 现在是 image 中要添加相应值的索引数组。您可以使用 np.add.at:

进行无缓冲添加
np.add.at(image, tuple(index.T), data[:, -1])

如果你的数据范围比坐标的边界框定义得更好,你可以通过不计算 coord.max()coord.min().

来节省一点时间

结果是这样的:

这整个操作在我的 10M 点的功率非常中等的机器上需要 6.4 秒,包括调用 plt.imshowplt.colorbar 和 运行 之前的垃圾收集。

在 IPython.

中使用 %%timeit 细胞魔法收集的时间

无论哪种方式,您都不到 450 小时。即使您的坐标变换不是线性合并,我希望您可以在合理的时间内 运行 只要您正确地对其进行矢量化。此外,多处理不太可能给您带来巨大的提升,因为它需要复制数据。