【问题标题】:Which numpy instructions are SIMD-optimized? How do I know?哪些 numpy 指令是 SIMD 优化的?我怎么知道?
【发布时间】:2021-12-20 01:10:48
【问题描述】:

对于简单的操作是显而易见的,例如A + Bnp.sum(A, axis=0),这些都是缓存优化的。

对于复杂的操作也很明显,例如对矩阵 AB 应用 FFT,这些都不是缓存优化的。

但是,这些问题是针对中间操作的,例如np.wherenp.apply_along_axis(这可能未优化)、np.einsum(这可能已优化)、np.vstack 等。我如何知道给定的 numpy 函数是否针对缓存命中进行了优化,并且它是比两个嵌套的for-loops 快吗?

【问题讨论】:

  • “两个 for 循环”很慢,因为它们是由 python 解释器执行的。 A+B 也在顶层进行解释,但对数组元素的迭代是在编译后的代码中完成的。
  • “缓存优化”和“缓存命中优化”是什么意思?

标签: numpy vectorization


【解决方案1】:

首先在 [numpy] simd 上进行 SO 搜索会找到许多答案。

一个 https://stackoverflow.com/a/45798012/901925 找到了一个 src/umath/simd.inc.src 文件。它将自己描述为“当前包含基于 amd64、x32 或非通用版本 (CFLAGS=-march=...) 构建的 sse2 函数”。这是低级代码,根据构建,可能会被合并到numpy 二进制文件中。这不是您作为 Python 级别的用户能够检测或控制的东西。

最近有很多点击的问题是How is numpy so fast?。 但答案主要涉及c++ 比较代码及其内存使用。所以它真的没有解决numpy的用法。

但出于您的目的,真正的问题是该操作是否使用已编译的 numpy 方法,或者是否使用 Python 级别的迭代和对象。

首先,您了解numpy 数组是如何存储的,它与列表有何不同?在不知道这种差异的情况下,许多关于 numpy 速度的讨论将难以理解。作为一般规则,使用数组就好像它们是列表一样,使用迭代和列表推导会更慢。在numpy 函数中使用列表会导致速度下降,因为列表必须首先转换为数组。

另外object dtype 数组将它们的数据存储在对象引用中,因此它们的计算以列表理解的速度运行。快速 numpy 方法仅适用于数字 dtypes,可以使用 c 原生类型编译的那些 - 浮点数、整数等。

至于你的示例表达式

A + B  

像这样的操作符被实现为ufunc,它充分利用了数组数据存储。由于它可以处理多维数组,并且使用broadcasting,因此底层代码非常复杂,不是您或我可以轻松阅读的内容。在某些较低级别上,它可能会利用处理器兑现和特殊指令,但这更多是c 代码宏和编译器选项的功能。

np.sum(A, axis=0)

sum实际上是一个np.add.reduce,所以上面的cmets适用。但是对于列表来说,原生 python sum 一点也不逊色。

np.where

np.nonzero 是更简单的编译函数之一。它首先使用np.count_nonzero 来查找有多少非零元素。它使用它来分配它将返回的数组元组,然后再次遍历参数以填充索引。它相当快,因为​​它在干净的c 代码中循环遍历数组的数据缓冲区。

np.apply_along_axis

这很慢,即使与列表推导相比也是如此。它必须为每个一维数组调用一次你的函数。这是对 python 函数的重复调用,它比实际的迭代方法花费的时间最多。像这样的函数不会编译你的函数,所以在某种程度上,它们只是 Python 级迭代的覆盖。 python代码可供学习。

np.einsum

这是一个复杂的函数,根据输入以不同的方式工作。对于更简单的情况,它只使用np.matmul/@,这可能非常快,具体取决于您拥有的BLAS 之类的库。多年前,当我为它编写补丁时,einsumcython 中使用了nditer

np.vstack

这是np.concatenate 的封面。 python代码很容易阅读。 concatenate 已编译。但是应该正确使用这些函数,并使用完整的数组列表。在循环中重复使用比列表append更糟糕。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-01-27
    • 1970-01-01
    • 2020-02-03
    • 1970-01-01
    • 2013-12-12
    • 1970-01-01
    • 2017-03-14
    • 1970-01-01
    相关资源
    最近更新 更多