《利用Python进行数据分析》 附录 A.9 性能技巧

附录A 高阶Numpy


A.9 性能技巧

利用NumPy从代码中获得良好性能通常很简单,因为数组操作通常会取代相对缓慢的纯Python循环。以下列表简要总结了一些需要注意的事项:

· 将Python循环和条件逻辑转换为数组操作和布尔数组操作

· 尽可能使用广播

· 使用数组视图(切片)来避免复制数据

· 使用ufunc和ufunc方法

如果在用尽NumPy提供的功能之后仍然无法获得所需的性能,请考虑在C、Fortran或Cython中编写代码。我在自己工作中经常会使用Cython进行一些微小开发,这是一种获得近乎C语言性能的方式。


A.9.1 连续内存的重要性

       尽管本主题的完整内容超出了本书的范围,但在某些应用中,数组的内存布局会显著影响计算速度。这种情况是基于CPU的缓存层次结构相关的性能差异。访问连续内存块的操作(例如,将C顺序数组的行相加)通常是最快的,因为存储器子系统会将适当的存储器块缓冲到超快的L1或L2 CPU缓存中。此外,NumPy的C代码库中的某些代码路径已进行优化,在连续内存的情况下可以避免对通用跨步内存的访问。

       如果说数组的内存布局是连续的,就意味着这些元素按照它们在Fortran顺序(列方向)或C顺序(行方向)排序中出现在数组中的次序存储在内存中。默认情况下,NumPy数组创建为C顺序连续或只是简单连续。因此,一个列方向的数组,例如C顺序数组的转置数组,可以称为是Fotran顺序连续的。这些属性都是可以通过ndarray的flags属性来检查的(见图A-1)

《利用Python进行数据分析》 附录 A.9 性能技巧_第1张图片
图A-1:ndarray的flags属性

       在这个例子中,对这些数组的行及逆行加和,在理论上arr_c是比arr_f更快,这是因为arr_c的行在内存中是连续的。这里我使用IPython中的%timeit进行检查(见图A-2)

《利用Python进行数据分析》 附录 A.9 性能技巧_第2张图片
图A-2:使用IPython中的%timeit进行检查

       当你想从NumPy中挤出更多的性能时,往往需要投入一些努力。如果你的数组没有所需的内存顺序,则可以使用copy并传递’C’或’F'(见图A-3)

《利用Python进行数据分析》 附录 A.9 性能技巧_第3张图片
图A-3:传递内存顺序、在数组上构建视图

你可能感兴趣的:(《利用Python进行数据分析》 附录 A.9 性能技巧)