Python 在大型numpy数组上使用布尔掩码非常慢

Python 在大型numpy数组上使用布尔掩码非常慢,python,performance,numpy,boolean,masking,Python,Performance,Numpy,Boolean,Masking,我在使用python编码时遇到了性能问题。 假设我有两个非常大的字符串数组(Nx2),比如N=12000000,还有两个变量label_a和label_b,它们也是字符串。以下是代码: import numpy as np import time indices = np.array([np.random.choice(np.arange(5000).astype(str),size=10000000),np.random.choice(np.arange(5000).astype(str),

我在使用python编码时遇到了性能问题。 假设我有两个非常大的字符串数组(Nx2),比如N=12000000,还有两个变量label_a和label_b,它们也是字符串。以下是代码:

import numpy as np
import time

indices = np.array([np.random.choice(np.arange(5000).astype(str),size=10000000),np.random.choice(np.arange(5000).astype(str),size=10000000)]).T
costs = np.random.uniform(size=10000000)

label_a = '2'
label_b = '9'

t0 = time.time()    

costs = costs[(indices[:,0]!=label_a)*(indices[:,0]!=label_b)*(indices[:,1]!=label_a)*(indices[:,1]!=label_b)]
indices = indices[(indices[:,0]!=label_a)*(indices[:,0]!=label_b)*(indices[:,1]!=label_a)*(indices[:,1]!=label_b)]

t1 = time.time()
toseq = t1-t0
print(toseq)
上面的代码段每次运行需要3秒钟。我希望在降低计算成本的同时实现同样的目标:
我使用布尔掩码仅检索costs and Indexes数组中的行,这些行的值不是如注释中所示的label_a和label_b,只计算一次所需索引的值,并将它们组合一次将节省时间

(为了简单起见,我还改变了计时方式——结果是一样的)

注意,我还添加了一个示例,其中操作不是基于字符串,而是基于数字。如果您可以避免使用字符串形式的值,而是使用数字,那么性能也会得到提升

如果你开始比较较长的标签,这个提升会非常显著——最后,如果字符串足够长的话,在过滤之前将字符串转换为数字可能是值得的

以下是我的结果:

0.9711 : run()
0.7065 : run_faster()
0.6983 : run_even_faster()
0.2657 : run_sep_mask()
0.4174 : run_sep_index()
0.4536 : run_even_faster_numerical()
两个
sep
条目显示,索引大约是构建
运行速度更快的掩码所需时间的两倍,因此,您只能期望对其进行更多的优化


但是,他们还表明,基于整数构建掩码比实际索引时间短0.04秒,而基于字符串构建掩码的时间约为0.26秒。所以,这就是你需要改进的地方。

你能提供一些关于
成本
指数
indix
成本
标签a
标签b
的示例数据吗?它不必是可伸缩的(因此,不是1200万个项目),只需几个项目就可以让您了解数据的类型,并显示您的代码实际工作。理想情况下,只需在代码示例的开头添加一些声明,这样它就可以作为一个整体工作。
idx=np。非零(索引…
成本[idx]
可能会减少时间。@Grismar done。谢谢,我也在考虑这个问题。@hpaulj我相信这让情况稍微好一点,在我的机器上,两行感兴趣的时间从2.6秒变为1.6秒。这是伟大的,我将从现在开始使用它。不过我还是希望能达到亚秒甚至更高的速度。您可能还希望分别计时mask/idx创建步骤和实际的索引步骤。我不记得以前的测试中,索引时间是否取决于所取值的比例(尽管这很容易测试)。如果mask Creation占主导地位,您可能需要将重点放在提高效率上。还要注意,我不喜欢使用全局变量,但我想接近原始代码-如果不需要,请不要使用全局变量。好的,我已经对代码进行了编辑,并实现了一个版本的run\u ever\u numerical()。非常感谢你的帮助!现在我把每次迭代的时间降到了0.4次,这需要30分钟多一点的时间来计算。该算法现在可能可用于大型数据集。不确定是否有其他方法可以提高性能,但不确定,直到我聘请了一名工程师,我认为,如果您的机器上运行
run\u sep\u index()
的值越来越接近,那么您可以做的事情就不多了,因为这只是
numpy
中的索引速度。您可能会考虑将这两个(成本和索引)结合起来,这样脚本只需索引一次-这可能是一个很好的折衷,因为在创建掩码时必须遍历稍大的数据集。
0.9711 : run()
0.7065 : run_faster()
0.6983 : run_even_faster()
0.2657 : run_sep_mask()
0.4174 : run_sep_index()
0.4536 : run_even_faster_numerical()