【问题标题】:In python, why is reading from an array slower than reading from list?在 python 中,为什么从数组读取比从列表读取慢?
【发布时间】:2011-03-17 08:30:54
【问题描述】:

我最近在学习python,并且正在使用该语言进行很多练习。

我发现有趣的一件事是,当我从数组中读取时,它几乎比 list 慢一半的时间。有人知道为什么吗?

这是我的代码:

从 timeit 导入计时器 导入数组 t = 10000 l = 范围(t) a = array.array('i', l) 定义列表(): 对于 xrange(t) 中的 i: l[i] 定义数组(): 对于 xrange(t) 中的 i: 一个[我] 打印计时器(列表).timeit(1000); 打印计时器(数组).timeit(1000);

输出是:

0.813191890717 1.16269612312

表示读取数组比列表慢。 我认为数组是一个固定大小的内存,而列表是一个动态结构。 所以我认为数组会比列表快。

有人解释一下吗?

【问题讨论】:

  • 可能的欺骗/答案:stackoverflow.com/questions/176011/… - 基本上 array.array 是一个 C 数组的包装器,所以我认为访问它时会有开销。不要用它来做数学。
  • 试图猜测 Python 的效率——尤其是对于那些来自类 C 背景的人——通常是违反直觉的。先写清楚代码,然后在衡量性能问题时进行优化;这也适用于 C,但因为语言元素非常接近人们经常忘记的机器。
  • 对于数学,你可能想使用 numpy(python 3 尚不可用),只有天知道为什么 numpy 不是标准库。
  • numpy 在 Python 3 上非常接近可用:mail-archive.com/numpy-discussion@scipy.org/msg26524.html

标签: python


【解决方案1】:

lists 是“动态增长的向量”(很像 C++ 的std::vector),但这绝不会减慢对它们的随机访问速度(它们不是链接 列表! -)。列表的条目是对 Python 对象(项目)的引用:访问一个只需要(在 CPython 中)项目引用计数的增量(在其他实现中,基于更高级的垃圾收集,甚至不是这样;-)。数组的条目是原始位和字节:访问一个需要基于该二进制值合成一个新的 Python 对象。例如:

$ python -mtimeit -s'import array; c=array.array("B", "bzap")' 'c[2]'
10000000 loops, best of 3: 0.0903 usec per loop
$ python -mtimeit -s'c=list("bzap")' 'c[2]'
10000000 loops, best of 3: 0.0601 usec per loop

30 纳秒的额外访问时间似乎还不错;-)。

顺便说一句,请注意timeit 在命令行中使用起来更好——自动选择重复、显示时间的测量单位等。这就是我一直使用它的方式(导入自定义编码如果需要,带有要调用的函数的模块——但这里没有必要)——它如此比从模块中导入和使用它更方便!

【讨论】:

    【解决方案2】:

    将原始整数包装到 Python int 中需要时间。

    【讨论】:

    • 确实如此。函数 LIST 只需递增然后递减每个列表元素的引用计数。另一方面,ARRAY 函数必须为每个整数分配内存(除了具有优化的较小整数),然后再次释放它。
    【解决方案3】:

    Python 列表在某些方面确实类似于普通数组,它们不是 Lisp 列表,但它们具有快速随机访问。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-03-11
      • 2018-11-17
      • 2019-11-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多