列表理解,映射和numpy.vectorize性能

问题描述 投票:11回答:4

我有一个函数foo(i),它需要一个整数,并且要花费大量时间才能执行。以下初始化a的任何方法之间是否会存在明显的性能差异:

a = [foo(i) for i in xrange(100)]

a = map(foo, range(100))

vfoo = numpy.vectorize(foo)
a = vfoo(range(100))

(我不在乎输出是列表还是numpy数组。)

还有更好的方法吗?

python performance numpy list-comprehension
4个回答
10
投票

[第一条评论:不要在样品中混合使用xrange()或range() ...这样做会使您的问题在您比较苹果和橙子时失效。

我第二个@Gabe的想法是,如果您具有许多大型数据结构,则numpy应该赢得整体...只是要记住,大多数时候C的速度要比Python快,但是大多数时候PyPy的速度要比Python快。 CPython。 :-)

就listcomps与map()调用而言...一个进行101个函数调用,而另一个进行102个函数调用。这意味着您不会在时间上有明显的不同,如下所示,使用timeit 模块,因为@Mike建议:

  • 列表理解

    $ python -m timeit "def foo(x):pass; [foo(i) for i in range(100)]"1000000 loops, best of 3: 0.216 usec per loop$ python -m timeit "def foo(x):pass; [foo(i) for i in range(100)]"1000000 loops, best of 3: 0.21 usec per loop$ python -m timeit "def foo(x):pass; [foo(i) for i in range(100)]"1000000 loops, best of 3: 0.212 usec per loop

  • [map()函数调用

    $ python -m timeit "def foo(x):pass; map(foo, range(100))"1000000 loops, best of 3: 0.216 usec per loop$ python -m timeit "def foo(x):pass; map(foo, range(100))"1000000 loops, best of 3: 0.214 usec per loop$ python -m timeit "def foo(x):pass; map(foo, range(100))"1000000 loops, best of 3: 0.215 usec per loop

尽管如此,除非您打算在using中计划使用这两种技术创建的列表,否则请尝试完全避免使用它们(使用列表)。 IOW,如果您要做的只是遍历它们,那么当您只关心一次查看每个元素时,只要丢弃该列表,就不值得消耗内存(并可能在内存中创建潜在的庞大列表)。完成了。

在这种情况下,我强烈建议使用generator表达式,因为它们不会在内存中创建整个列表...这是一种更友好的内存,通过元素循环进行处理的惰性迭代方式没有在内存中创建大型数组。最好的部分是它的语法几乎与listcomps相同:

a = (foo(i) for i in range(100))

仅[2.x用户]]:沿着更多的迭代路线,将任何较旧的2.x代码的所有range()调用都更改为xrange(),然后在移植到Python 3时切换到range(),其中[ C0]替换并重命名为xrange()


18
投票
  • 您为什么要对此进行优化?您是否编写了经过测试的有效代码,然后检查了算法range(),并发现优化此方法会产生效果?您是否在一个深层的内循环中这样做,发现自己在浪费时间?如果没有,请不要打扰。


7
投票

3
投票
© www.soinside.com 2019 - 2024. All rights reserved.