繁体   English   中英

加速Numpy阵列上的循环

[英]Speeding up loops over a Numpy array

在我的代码中,我有for循环,它在多维numpy数组上进行索引,并使用在每次迭代时获得的子数组进行一些操作。 看起来像这样

for sub in Arr:
  #do stuff using sub

现在使用sub完成的东西是完全矢量化的,所以它应该是高效的。 另一方面,这个循环迭代约~10^5次并且是瓶颈。 你认为我会通过将这部分卸载到C来获得改进吗。我有点不愿意这样做,因为do stuff using sub广播,切片,智能索引技巧,这些技巧在简单的C中写作会很乏味。我也会欢迎在将计算卸载到C时如何处理广播,切片,智能索引的想法和建议。

如果你无法“矢量化”整个操作并且循环确实是瓶颈,那么我强烈建议使用Cython。 我最近一直在讨论它,它很容易使用,并且有一个像numpy一样的接口。 对于像langevin集成商这样的东西,我看到了比numpy中的体面实现快115倍的速度。 请参阅此处的文档:

http://docs.cython.org/src/tutorial/numpy.html

我也建议看下面的论文

只需键入输入数组和循环计数器,您就可以看到令人满意的加速,但如果您想充分发挥cython的潜力,那么您将不得不对等效广播进行硬编码。

你可以看看scipy.weave 您可以使用scipy.weave.blitz将表达式透明地转换为C++代码并运行它。 它将自动处理切片并摆脱临时性,但你声称你的for循环体不会创造临时性,所以你的milage可能会有所不同。

但是,如果您想用更高效的东西替换整个for循环,那么您可以使用scipy.inline 缺点是你必须编写C++代码。 这应该不会太难,因为你可以使用非常接近numpy数组表达式的Blitz++语法。 直接支持切片,但广播却不支持。

有两种解决方法:

  1. 是使用numpy-C api并使用多维迭代器。 他们透明地处理广播。 但是,您正在调用Numpy运行时,因此可能会有一些开销。 另一种选择,可能更简单的选择是使用通常的矩阵表示法进行广播。 广播操作可以写成具有所有1的向量的外部产品。 好消息是Blitz++实际上不会在内存中创建这个临时广播数组,它会弄清楚如何将它包装到一个等效的循环中。

  2. 对于第二种选择,请查看http://www.oonumerics.org/blitz/docs/blitz_3.html#SEC88以获取索引占位符。 只要您的矩阵小于11维,您就可以了。 此链接显示了它们如何用于形成外部产品http://www.oonumerics.org/blitz/docs/blitz_3.html#SEC99 (搜索外部产品以转到文档的相关部分)。

除了使用Cython之外,您还可以在Fortran中编写瓶颈部分。 然后使用f2py将其编译为Python .pyd文件。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM