15

我使用numpy.array()函数从列表中创建numpy.float64标准数组。

我注意到,当列表包含None或提供列表列表时,这是非常缓慢的。

下面是一些时间示例。有明显的解决方法,但为什么这么慢?

无列表示例:

###使用None列表调用array()的速度非常慢在[3]中:%timeit numpy.array([None]*100000,dtype=numpy.float64)1个回路,最好为3:240 ms/回路###零数组不存在问题在[4]中:%timeit numpy.array([0.0]*100000,dtype=numpy.float64)100个回路,最好为3:9.94 ms/回路###如果使用dtype=object并将其转换为float64,则速度也会很快在[5]中:%timeit numpy.array([None]*100000,dtype=numpy.object).astype(numpyfloat64)100个回路,最好为3:4.92 ms/回路###如果使用数组()的fromiter()insead,也会很快在[6]中:%timeit numpy.fromiter([None]*100000,dtype=numpyfloat64)100个回路,最好为3:3.29 ms/回路

列表列表示例:

###创建列矩阵的速度非常慢在[7]中:%timeit numpy.array([[0.0]]*100000,dtype=numpy.float64)1个回路,每个回路最好为3:353 ms###创建列向量和重塑形状没有问题在[8]中:%timeit numpy.array([0.0]*100000,dtype=numpy.foat64).reform((-1,1))100个回路,每回路最佳3:10 ms###可以使用itertools展平输入列表在[9]中:%timeit numpy.fromiter(itertools.chain.from_iterable([0.0]]*100000),dtype=numpy.float64).reshape((-1,1))100个回路,最好为3:9.65 ms/回路
7
  • 7
    要创建空数组,请使用a=numpy.empy(100000)。要创建一个全为零的数组:a=numpy.zeros(100000).
    – jfs公司
    评论 2013年5月29日16:33
  • 我的目标不是创建一个零或空的数组,但当数据集中出现None时,我会遇到性能问题。如果我创建数组并首先设置值,我会遇到几乎相同的问题。在[18]中:a=numpy.empy((100000,))在[19]中:%timeit a[:]=[None]*100000 1个循环,每循环最佳3:209 ms在[20]中:%timeit a]:]=[0]*100000100个循环,每个循环最佳3:9.59 ms
    – 标记W
    评论 2013年5月29日16:37
  • 实际上,这是一个有趣的问题:为什么[3]比…慢得多[5](这可能是一个bug,或者只是一个未优化的罕见用例)。重复NaN公司,呼叫numpy.repeat(浮点(“nan”),100000) 评论 2013年5月29日17:52
  • 谢谢JF,这是我的问题,为什么[3]和[7]这么慢,而其他的都是类似的,这么快。我们的pyodbc数据库查询通常返回放入darray中的float和None列表。我想这种情况并不是那么罕见。
    – 标记W
    评论 2013年5月29日18:09
  • 将列表列表分配给空数组也很有趣(a[…]=[[1]]*100000)比慢50倍[8](分配行很快)。我想找到瓶颈需要分析C代码。。。无论如何,这是一个好问题。 评论 2013年5月29日18:27

2个答案2

重置为默认值

我已经报道了这是一个无聊的问题。报告和修补程序文件如下:

https://github.com/numpy/numpy/issues/3392

修补后:

#为240 ms,最佳替代版本为3.29在[5]中:%timeit numpy.array([无]*100000)100个回路,最好为3:7.49 ms/回路#为353 ms,最佳替代版本为9.65在[6]中:%timeit numpy.array([0.0]]*100000)10个回路,最好为3:23.7 ms/回路
1

我猜转换列表的代码只是调用浮动一切都是如此。如果参数定义__浮子__,我们称之为,否则我们将其视为字符串(对None抛出异常,我们捕获该异常并将其放入np编号). 异常处理应该相对较慢。

时机似乎验证了这一假设:

将numpy导入为np%timeit[无]*100000>1000个回路,最好为3:1.04 ms/回路%timeit np.array([0.0]*100000)>10个回路,最好为3:21.3 ms/回路%timeit[0.0]*100000]中i的[i.__float_()>10个回路,每个回路最好为3:32 ms定义flt(d):尝试:回流浮子(d)除:返回np.nan%timeit np.array([无]*100000,dtype=np.float64)>1个回路,每个回路最好为3:477 ms%时间[flt(d)for d in[None]*100000]>1个回路,每个回路最好为3:328ms

添加另一个案例,以明确我的观点。如果明确选中“无”,则速度不会超过此速度:

定义flt2(d):如果d为无:返回np.nan尝试:回流浮子(d)除:返回np.nan%timeit[flt2(d)for d in[None]*100000]>10个回路,每个回路最好为3:45 ms
  • 我发现你的假设很有趣,尽管你得到的时间差异(大约快1.5倍)仍然不支持你的论点,因为OP的时间差异大约是35倍。。。。你可以继续朝这个方向努力 评论 2013年6月1日7:45
  • @是的,如果我想深入挖掘的话,下一步就是查看源代码。虽然我知道:如果他们明确检查,不会这么慢。
    – U2EF1型
    评论 2013年6月1日17:53
  • 1
    我挖得更深了。代码花费了所有的时间来抛出执行。它没有将事物视为字符串,而是为许多没有属性或不是缓冲区的事物调用getattr或getbuffer。这两者都会创建并忽略异常。我调整了common.c和ctor.c以避免这些情况,性能更符合您的期望。
    – 标记W
    评论 2013年6月3日13:11

你的答案

单击“发布您的答案”,表示您同意我们的服务条款并确认您已阅读我们的隐私政策.

不是你想要的答案吗?浏览标记的其他问题问你自己的问题.