1亿个零的高效Python数组?

2024-03-29 08:49:07 发布

您现在位置:Python中文网/ 问答频道 /正文

在Python中,初始化和访问大型数组元素的有效方法是什么?

我想用Python创建一个数组,其中有1亿个条目,无符号的4字节整数,初始化为零。我想要快速的数组访问,最好是连续内存。

奇怪的是,NumPy数组的执行速度似乎非常慢。我可以试试别的办法吗?

有一个array.array模块,但是我看不到一个有效地分配1亿个条目块的方法。

对评论的答复:

  • 我不能使用稀疏数组。对于这个算法来说太慢了,因为数组变得非常密集。
  • 我知道Python是被解释的,但肯定有一种方法可以进行快速的数组操作?
  • 我做了一些分析,每秒用NumPy获得大约160K个数组访问(按索引查找或更新元素)。这看起来很慢。

Tags: 模块方法内存numpy算法元素字节评论
3条回答

我做了一些分析,结果完全违背直觉。 对于简单的数组访问操作,numpy和array.array比原生Python数组慢10倍。

注意,对于数组访问,我正在执行以下形式的操作:

a[i] += 1

个人资料:

  • [0]*2000万

    • 通道:2.3M/秒
    • 初始化:0.8s
  • numpy.zeros(shape=(20000000,),dtype=numpy.int32)

    • 接入:160K/秒
    • 初始化:0.2s
  • array.array('L',[0]*20000000)

    • 访问:175K/秒
    • 初始化:2.0s
  • array.array('L',(0表示范围(20000000)内的i)

    • 访问:175K/秒,大概是基于另一个数组的配置文件
    • 初始化:6.7s

只是提醒一下Python的整数是如何工作的:如果通过

a = [0] * K

您需要列表的内存(sizeof(PyListObject) + K * sizeof(PyObject*))和单个整数对象的内存0。只要列表中的数字保持在Python用于缓存的魔法数字V以下,就可以了,因为这些数字是共享的,即任何指向数字的名称n < V都指向完全相同的对象。您可以使用以下代码段找到此值:

>>> i = 0
>>> j = 0
>>> while i is j:
...    i += 1
...    j += 1
>>> i # on my system!
257 

这意味着一旦计数超过这个数字,您需要的内存就是sizeof(PyListObject) + K * sizeof(PyObject*) + d * sizeof(PyIntObject),其中d < KV (== 256)上的整数数。在64位系统上,sizeof(PyIntObject) == 24sizeof(PyObject*) == 8,即最坏情况下的内存消耗是320000000字节。

使用numpy.ndarrayarray.array,初始化后内存消耗是恒定的,但是您要为透明创建的包装器对象付费,正如Thomas Wouters所说。可能,您应该考虑使用Cython^{}将更新代码(访问并增加数组中的位置)转换为C代码。

试试这个:

x = [0] * 100000000

在我的机器上执行只需几秒钟,访问接近即时。

相关问题 更多 >