繁体   English   中英

在numpy中更新整数索引切片的快速方法

[英]Fast way to update integer indexed slice in numpy

我有一个很大的numpy数组,并且我要清理数据(这是伪代码):

arr = np.ones(shape=(int(5E5), 1000), dtype=float)
to_zero = np.arange(500, 1000, 2) # Normally this is a function that finds 
                                  # columns be zeroed indexes are not continous
arr[:, to_zero] = 0

问题是arr[:, to_zero] = 0需要很长时间。 在此示例中,此过程需要4秒钟。 arr[:, :500]需要500毫秒。

有什么办法可以使速度更快?

numpy 1.8.1numpy 1.9 beta的 numpy笔记本示例(请参阅计时结果)。

正如@Jaime指出的那样,从长远来看,使用较新的numpy是一个不错的选择。

从numpy的内部存储角度来看,重置大量连续内存非常快。 以您的示例为例,问题在于您正在将内存调零,就像疯了的兔子一样在内存中跳跃。

我尝试将数组反过来旋转,然后速度几乎提高了3倍。对于您的版本,我得到4.08 s,对于换位版本,我得到1.57 s。 因此,如果您可以否则,至少这是一个很好的优化。

此索引在numpy中可能有些麻烦,因为实际上是在做:

for c in to_zero:
    arr[:, c] = 0

比使用列表符号更快。

因此,我运行了几种不同的选择:

to_zero = numpy.arange(0, 500, 2)

# 1. table in the original orientation
arr = numpy.ones((500000, 1000), dtype='float')

# 1.1. basic case: 4.08 s
arr[:, to_zero] = 0

# 1.2. a bit different notation: 234 ms 
arr[:, 0:500:2] = 0

# 1.3. for loop: 2.75 s
for c in to_zero:
    arr[:, c] = 0

# 2. transposed table
arr = numpy.ones((1000, 500000), dtype='float')

# 2.1. basic case: 1.47 s
arr[to_zero,:] = 0

# 2.2. a bit different notation: 105 ms 
arr[0:500:2,:] = 0

# 2.3. for loop: 112 ms
for r in to_zero:
    arr[r, :] = 0

这些已使用IPython%timeit进行了计时,因此一次运行到另一次运行的结果可能有所不同,但似乎存在一种模式。 转置表并使用循环。

问题必须与在内存中分配数据的方式有关。

但是要解决您的问题,请将行读取为列,将列读取为行:

arr = np.ones(shape=(1000, int(5E5)), dtype=float)
to_zero = np.arange(500, 1000, 2) # Normally this is a function that finds 
                              # columns be zeroed indexes are not continous
arr[to_zero, :] = 0

暂无
暂无

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

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