numpy - 哪些 numpy 指令是 SIMD 优化的?我怎么知道?
问题描述
很明显,对于简单的操作,例如A + B
,np.sum(A, axis=0)
这些是缓存优化的。
A
对于复杂的操作,例如在矩阵,上应用 FFT 也很明显B
,这些都不是缓存优化的。
但是,问题是针对中间操作的,例如np.where
,np.apply_along_axis
(这可能未优化)、np.einsum
(这可能已优化)np.vstack
等。我如何知道给定的 numpy 函数是否针对缓存命中进行了优化,并且它是比两个嵌套循环快for
?
解决方案
首先,SO 搜索[numpy] simd
会出现许多答案。
一,https://stackoverflow.com/a/45798012/901925,找到了一个src/umath/simd.inc.src
文件。它将自己描述为“当前包含基于 amd64、x32 或非通用版本 (CFLAGS=-march=...) 构建的 sse2 函数”。这是低级代码,根据构建,可能会被合并到numpy
二进制文件中。这不是您作为 Python 级别的用户将能够检测或控制的东西。
最近有很多点击的问题是 numpy 怎么这么快?. 但答案主要涉及c++
比较代码及其内存使用。所以它真的没有解决numpy
用法。
但是出于您的目的,真正的问题是操作是否使用编译numpy
方法,或者是否使用 Python 级别的迭代和对象。
首先,您了解numpy
数组是如何存储的,以及它与列表有何不同?在不知道这种差异的情况下,许多关于 numpy 速度的讨论将难以理解。作为一般规则,使用数组就好像它们是列表一样,使用迭代和列表推导会更慢。并且在numpy
函数中使用列表会导致速度损失,因为列表必须首先转换为数组。
dtype 数组也object
将它们的数据存储在对象引用中,因此它们的计算以列表理解的速度运行。快速 numpy 方法仅适用于数字 dtypes,可以用c
本机类型编译的那些 - 浮点数、整数等。
至于您的示例表达式
A + B
像这样的运算符被实现为ufunc
,它充分利用了数组数据存储。由于它可以与多维数组一起工作,并且使用broadcasting
的底层代码相当复杂,而且不是您或我可以轻松阅读的内容。在某些较低级别上,它可能会利用处理器兑现和特殊指令,但这更多是c
代码宏和编译器选项的功能。
np.sum(A, axis=0)
sum
实际上是 a np.add.reduce
,所以上述评论适用。但是对于列表,本机 pythonsum
毫不逊色。
np.where
np.nonzero
是较简单的编译函数之一。它首先用于np.count_nonzero
查找有多少非零元素。它使用它来分配它将返回的数组元组,然后再次遍历参数以填充索引。c
它相当快,因为它以干净的代码循环遍历数组的数据缓冲区。
np.apply_along_axis
即使与列表推导相比,这也很慢。它必须为每个一维数组调用一次你的函数。这是对 python 函数的重复调用,它比实际的迭代方法花费的时间最多。像这样的函数不会编译你的函数,所以在某种程度上,它们只是 Python 级迭代的覆盖。python代码可供研究。
np.einsum
这是一个复杂的功能,根据输入以不同的方式工作。对于更简单的情况,它只使用np.matmul/@
,这可能非常快,具体取决于BLAS
您拥有的类似库。多年前,当我为它写了一个补丁时,einsum
在.nditer
cython
np.vstack
这是一个封面np.concatenate
。python代码很容易阅读。 concatenate
被编译。但是这些函数应该正确使用,带有完整的数组列表。在循环中重复使用比 list 更糟糕append
。
推荐阅读
- visual-studio-code - How to use cpx when debugging in VS Code?
- javascript - Send a value in ajax
- angular - 使用 Jest 和 Angular 5 测试效果
- reactjs - React router 4 and path params in layouts
- excel - Excel 在 VLOOKUP 中使用 VLOOKUP 作为查找值会导致值错误
- javascript - Vuejs - 提交属性时的 Vuex 行为
- java - RxJava call the network when database is empty
- angularjs - One way binding doesn't work in AngularJS with setInterval
- javascript - Sequelize Deprecated Error Message when running migration
- angular - Angular 5 HttpClient 无法填充变量文本