CPU 构建选项#

概述#

NumPy 提供配置选项以根据 CPU 功能优化性能。这些选项允许您指定要支持的 CPU 功能,平衡性能、兼容性和二进制大小。本文档解释了如何在各种 CPU 架构中有效使用这些选项。

关键配置选项#

NumPy 使用多个构建选项来控制 CPU 优化。

  • cpu-baseline:编译的 NumPy 运行所需的最低 CPU 功能集。

    • 默认值:min(提供跨广泛平台的兼容性)

    • 如果您的目标 CPU 不支持所有指定的基线功能,NumPy 将会因 Python 运行时错误而无法加载。

  • cpu-baseline-detect:控制基于编译器标志的 CPU 基线检测。默认值为 auto,如果在编译时使用了 -march= 或类似的编译器标志,则会启用检测。其他可能的值是 enableddisabled,分别无条件地启用或禁用它。

  • cpu-dispatch:将生成优化代码路径的额外 CPU 功能。

    • 默认值:max(启用所有可用优化)

    • 运行时,NumPy 会根据您的 CPU 功能自动选择最快的可用代码路径。

  • disable-optimization:完全禁用所有 CPU 优化。

    • 默认值:false(启用优化)

    • 当设置为 true 时,将禁用所有 CPU 优化的代码,包括调度、SIMD 和循环展开。

    • 对于调试、测试或优化可能导致问题的环境非常有用。

这些选项通过 meson-python 参数在构建时指定。

pip install . -Csetup-args=-Dcpu-baseline="min" -Csetup-args=-Dcpu-dispatch="max"
# or through spin
spin build -- -Dcpu-baseline="min" -Dcpu-dispatch="max"

cpu-baselinecpu-dispatch 可以设置为特定的 CPU 组、功能,或执行特定操作的 特殊选项。以下各节将详细介绍这些选项。

常见用法场景#

仅为本地使用进行构建#

仅为您的计算机构建,且不打算分发时。

python -m build --wheel -Csetup-args=-Dcpu-baseline="native" -Csetup-args=-Dcpu-dispatch="none"

此选项会自动检测并使用您计算机上的所有可用 CPU 功能。

注意

如果主机平台不支持 native,则会引发致命错误。

排除特定功能#

您可能希望从调度功能中排除某些 CPU 功能。

# For x86-64: exclude all AVX-512 features
python -m build --wheel -Csetup-args=-Dcpu-dispatch="max -X86_V4"

# For ARM64: exclude SVE
python -m build --wheel -Csetup-args=-Dcpu-dispatch="max -SVE"

注意

排除某个功能也会排除该功能所隐含的任何后续功能。例如,排除 X86_V4 会同时排除 AVX512_ICLAVX512_SPR

针对较旧的 CPU#

x86-64 上,默认基线设置为 min,它映射到 X86_V2。这不适用于较旧的 CPU(2009 年之前)或旧的虚拟机。要解决此问题,请将基线设置为 none

python -m build --wheel -Csetup-args=-Dcpu-baseline="none"

这将创建一个与所有 x86 CPU 兼容的构建,但基线没有任何手动优化或 SIMD 代码路径。构建将仅依赖于调度代码路径进行优化。

针对较新的 CPU#

提高基线性能主要有两个原因:

  1. 调度内核不覆盖所有代码路径。

  2. 更高的基线导致更小的二进制文件大小,因为编译器不会为排除的调度功能生成代码路径。

对于 2015 年及更新的 CPU,将基线设置为 X86_V3 可能就足够了。

python -m build --wheel -Csetup-args=-Dcpu-baseline="min+X86_V3"

按架构支持的 CPU 功能#

NumPy 支持多种 CPU 架构的优化代码路径。以下是每种架构支持的功能组。功能组的名称可用于构建选项 cpu-baselinecpu-dispatch

X86#

名称

隐含

包含

X86_V2

SSE SSE2 SSE3 SSSE3 SSE4_1 SSE4_2 POPCNT CX16 LAHF

X86_V3

X86_V2

AVX AVX2 FMA3 BMI BMI2 LZCNT F16C MOVBE

X86_V4

X86_V3

AVX512F AVX512CD AVX512VL AVX512BW AVX512DQ

AVX512_ICL

X86_V4

AVX512VBMI AVX512VBMI2 AVX512VNNI AVX512BITALG AVX512VPOPCNTDQ AVX512IFMA VAES GFNI VPCLMULQDQ

AVX512_SPR

AVX512_ICL

AVX512FP16

这些组对应于 CPU 代。

  • X86_V2:x86-64-v2 微架构(2009 年以来的 CPU)

  • X86_V3:x86-64-v3 微架构(2015 年以来的 CPU)

  • X86_V4:x86-64-v4 微架构(支持 AVX-512 的 CPU)

  • AVX512_ICL:Intel Ice Lake 及类似 CPU

  • AVX512_SPR:Intel Sapphire Rapids 及更新的 CPU

注意

在 32 位 x86 上,cx16 已从 X86_V2 中排除。

在 IBM/POWER 大端序#

名称

隐含

VSX

VSX2

VSX

VSX3

VSX VSX2

VSX4

VSX VSX2 VSX3

在 IBM/POWER 小端序#

名称

隐含

VSX

VSX2

VSX2

VSX

VSX3

VSX VSX2

VSX4

VSX VSX2 VSX3

在 ARMv7/A32#

名称

隐含

NEON

NEON_FP16

NEON

NEON_VFPV4

NEON NEON_FP16

ASIMD

NEON NEON_FP16 NEON_VFPV4

ASIMDHP

NEON NEON_FP16 NEON_VFPV4 ASIMD

ASIMDDP

NEON NEON_FP16 NEON_VFPV4 ASIMD

ASIMDFHM

NEON NEON_FP16 NEON_VFPV4 ASIMD ASIMDHP

在 ARMv8/A64#

名称

隐含

NEON

NEON_FP16 NEON_VFPV4 ASIMD

NEON_FP16

NEON NEON_VFPV4 ASIMD

NEON_VFPV4

NEON NEON_FP16 ASIMD

ASIMD

NEON NEON_FP16 NEON_VFPV4

ASIMDHP

NEON NEON_FP16 NEON_VFPV4 ASIMD

ASIMDDP

NEON NEON_FP16 NEON_VFPV4 ASIMD

ASIMDFHM

NEON NEON_FP16 NEON_VFPV4 ASIMD ASIMDHP

在 IBM/ZSYSTEM(S390X)#

名称

隐含

VX

VXE

VX

VXE2

VX VXE

在 RISCV64#

名称

隐含

RVV

特殊选项#

除了特定的功能名称外,您还可以使用这些特殊值:

NONE#

启用所有功能(等同于空字符串)。

NATIVE#

启用主机 CPU 支持的所有功能。

DETECT#

检测编译器启用的功能。如果环境变量 CFLAGS 中设置了 -march-mcpu-xhost/QxHost,则此选项将默认附加到 cpu-baseline,除非 cpu-baseline-detect 被设置为 disabled

MIN#

为每种架构启用最低 CPU 功能。

对于架构

隐含

x86(32 位)

X86_V2

x86-64

X86_V2

IBM/POWER(大端序)

IBM/POWER(小端序)

VSX VSX2

ARMv7/ARMHF

ARMv8/AArch64

NEON NEON_FP16 NEON_VFPV4 ASIMD

IBM/ZSYSTEM(S390X)

riscv64

MAX#

启用编译器和平台支持的所有功能。

运算符(-/+#

移除或添加特定功能,与 MAXMINNATIVE 结合使用非常方便。

  • 添加功能(+)会包含所有隐含功能。

  • 移除功能(-)会排除所有隐含已移除功能的后续功能。

示例

python -m build --wheel -Csetup-args=-Dcpu-dispatch="max-X86_V4"
python -m build --wheel -Csetup-args=-Dcpu-baseline="min+X86_V4"

用法和行为#

不区分大小写#

CPU 功能和选项不区分大小写。

python -m build --wheel -Csetup-args=-Dcpu-dispatch="X86_v4"

混合跨架构的功能#

您可以混合使用不同架构的功能。

python -m build --wheel -Csetup-args=-Dcpu-baseline="X86_V4 VSX4 SVE"

顺序无关性#

指定功能的顺序无关紧要。

python -m build --wheel -Csetup-args=-Dcpu-dispatch="SVE X86_V4 x86_v3"

分隔符#

您可以使用空格或逗号作为分隔符。

# All of these are equivalent
python -m build --wheel -Csetup-args=-Dcpu-dispatch="X86_V2 X86_V4"
python -m build --wheel -Csetup-args=-Dcpu-dispatch=X86_V2,X86_V4

功能组合#

选项中指定的功能会自动与所有隐含功能组合。

python -m build --wheel -Csetup-args=-Dcpu-baseline=X86_V4

等同于

python -m build --wheel -Csetup-args=-Dcpu-baseline="X86_V2 X86_V3 X86_V4"

基线重叠#

cpu-baseline 中指定的功能将从 cpu-dispatch 功能中排除,以及它们所隐含的功能,但不会排除隐含它们的功能的后续功能。

例如,如果您指定 cpu-baseline="X86_V4",它将从 cpu-dispatch 功能中排除 X86_V4 及其隐含功能 X86_V2X86_V3

编译时检测#

将功能指定给 cpu-dispatchcpu-baseline 并不会显式启用它们。功能在编译时进行检测,并根据工具链和平台支持,根据您指定的选项启用最大可用功能。

此检测通过包含指定功能通用内在函数的编译时源文件,在编译器中测试功能可用性来完成。如果编译器和汇编器都支持该功能,则会启用它。

例如,如果您指定 cpu-dispatch="AVX512_ICL" 但您的编译器不支持,该功能将在构建中被排除。但是,如果其他隐含功能受支持,它们仍会被启用。

平台差异#

对于某些编译器或架构,一些特殊情况迫使我们将某些功能链接在一起,导致无法单独构建它们。

这些情况可分为两部分,如下所示:

架构兼容性

需要对同一架构的连续代 CPU 所确保支持的某些 CPU 功能进行对齐,在某些情况下。

  • 在 ppc64le 上,VSX (ISA 2.06)VSX2 (ISA 2.07) 都隐含了对方,因为支持小端序模式的第一代是 Power-8 (ISA 2.07)

  • 在 AArch64 上,NEON NEON_FP16 NEON_VFPV4 ASIMD 隐含了彼此,因为它们是硬件基线的一部分。

例如:

# On ARMv8/A64, specify NEON is going to enable Advanced SIMD
# and all predecessor extensions
python -m build --wheel -Csetup-args=-Dcpu-baseline=neon
# which is equivalent to
python -m build --wheel -Csetup-args=-Dcpu-baseline="neon neon_fp16 neon_vfpv4 asimd"

注意

请仔细查看 按架构支持的 CPU 功能,以确定相互隐含的功能。

构建报告#

在大多数情况下,CPU 构建选项不会产生导致构建中断的致命错误。构建日志中出现的大多数错误是由于编译器缺少某些预期的 CPU 功能而发出的警告。

因此,我们强烈建议检查最终报告日志,以了解启用了哪些 CPU 功能以及哪些未启用。

您可以通过跟踪 meson 构建日志找到 CPU 优化报告,以下是 x86_64/gcc 上的示例:

Test features "X86_V2" : Supported 
Test features "X86_V3" : Supported 
Test features "X86_V4" : Supported 
Test features "AVX512_ICL" : Supported 
Test features "AVX512_SPR" : Supported 
Configuring npy_cpu_dispatch_config.h using configuration
Message: 
CPU Optimization Options
  baseline:
    Requested : min
    Enabled   : X86_V2
  dispatch:
    Requested : max
    Enabled   : X86_V3 X86_V4 AVX512_ICL AVX512_SPR

Generating multi-targets for "_umath_tests.dispatch.h" 
  Enabled targets: X86_V3, baseline
Generating multi-targets for "argfunc.dispatch.h" 
  Enabled targets: X86_V4, X86_V3, baseline
Generating multi-targets for "x86_simd_argsort.dispatch.h" 
  Enabled targets: X86_V4, X86_V3
Generating multi-targets for "x86_simd_qsort.dispatch.h" 
  Enabled targets: X86_V4, X86_V3
Generating multi-targets for "x86_simd_qsort_16bit.dispatch.h" 
  Enabled targets: AVX512_SPR, AVX512_ICL
Generating multi-targets for "highway_qsort.dispatch.h" 
  Enabled targets: 
Generating multi-targets for "highway_qsort_16bit.dispatch.h" 
  Enabled targets: 
Generating multi-targets for "loops_arithm_fp.dispatch.h" 
  Enabled targets: X86_V3, baseline
Generating multi-targets for "loops_arithmetic.dispatch.h" 
  Enabled targets: X86_V4, X86_V3, baseline
Generating multi-targets for "loops_comparison.dispatch.h" 
  Enabled targets: X86_V4, X86_V3, baseline
Generating multi-targets for "loops_exponent_log.dispatch.h" 
  Enabled targets: X86_V4, X86_V3, baseline
Generating multi-targets for "loops_hyperbolic.dispatch.h" 
  Enabled targets: X86_V4, X86_V3, baseline
Generating multi-targets for "loops_logical.dispatch.h" 
  Enabled targets: X86_V4, X86_V3, baseline
Generating multi-targets for "loops_minmax.dispatch.h" 
  Enabled targets: X86_V4, X86_V3, baseline
Generating multi-targets for "loops_modulo.dispatch.h" 
  Enabled targets: baseline
Generating multi-targets for "loops_trigonometric.dispatch.h" 
  Enabled targets: X86_V4, X86_V3, baseline
Generating multi-targets for "loops_umath_fp.dispatch.h" 
  Enabled targets: X86_V4, baseline
Generating multi-targets for "loops_unary.dispatch.h" 
  Enabled targets: X86_V4, baseline
Generating multi-targets for "loops_unary_fp.dispatch.h" 
  Enabled targets: baseline
Generating multi-targets for "loops_unary_fp_le.dispatch.h" 
  Enabled targets: baseline
Generating multi-targets for "loops_unary_complex.dispatch.h" 
  Enabled targets: X86_V3, baseline
Generating multi-targets for "loops_autovec.dispatch.h" 
  Enabled targets: X86_V3, baseline
Generating multi-targets for "loops_half.dispatch.h" 
  Enabled targets: AVX512_SPR, X86_V4, baseline
WARNING: Project targets '>=1.5.2' but uses feature deprecated since '1.3.0': Source file src/umath/svml/linux/avx512/svml_z0_acos_d_la.s in the 'objects' kwarg is not an object..
Generating multi-targets for "_simd.dispatch.h" 
  Enabled targets: X86_V3, X86_V4, baseline

运行时调度#

导入 NumPy 会触发对可用 CPU 功能的扫描,这些功能来自可调度功能集。您可以通过将环境变量 NPY_DISABLE_CPU_FEATURES 设置为逗号、制表符或空格分隔的功能列表来禁用某些功能。

例如,在 x86_64 上,这将禁用 X86_V4

NPY_DISABLE_CPU_FEATURES="X86_V4"

如果解析失败或功能未通过 cpu-dispatch 构建选项启用,则会引发错误。如果功能已通过构建支持但在当前 CPU 上不可用,则会发出警告。

跟踪调度函数#

您可以使用 Python 函数 numpy.lib.introspect.opt_func_info 来发现不同优化函数启用的 CPU 目标。

此函数提供两个可选参数用于过滤结果:

  1. func_name - 用于细化函数名称。

  2. signature - 用于指定签名中的数据类型。

例如:

 >> func_info = numpy.lib.introspect.opt_func_info(func_name='add|abs', signature='float64|complex64')
 >> print(json.dumps(func_info, indent=2))
 {
  "absolute": {
    "dd": {
      "current": "baseline(X86_V2)",
      "available": "baseline(X86_V2)"
    },
    "Ff": {
      "current": "X86_V3",
      "available": "X86_V3 baseline(X86_V2)"
    },
    "Dd": {
      "current": "X86_V3",
      "available": "X86_V3 baseline(X86_V2)"
    }
  },
  "add": {
    "ddd": {
      "current": "X86_V3",
      "available": "X86_V3 baseline(X86_V2)"
    },
    "FFF": {
      "current": "X86_V3",
      "available": "X86_V3 baseline(X86_V2)"
    }
  }
}