CPU 构建选项#

描述#

以下选项主要用于更改针对特定 CPU 特性优化的默认行为

  • cpu-baseline:所需 CPU 特性的最小集合。

    默认值为 min,它提供了一系列处理器家族中可以在各种平台上安全运行的最低 CPU 特性。

    注意

    在运行时,如果目标 CPU 不支持任何指定的特性(会引发 Python 运行时错误),NumPy 模块将无法加载。

  • cpu-dispatch:额外 CPU 特性的调度集合。

    默认值为 max -xop -fma4,它启用所有 CPU 特性,但 AMD 传统特性除外(X86 架构下)。

    注意

    在运行时,如果目标 CPU 中不可用,NumPy 模块将跳过任何指定的特性。

这些选项在构建时可通过构建前端(例如 pipbuild)将设置参数传递给 meson-python 来访问。它们接受一组 CPU 特性 或聚合了多个特性的特性组,或者执行一系列过程的 特殊选项

自定义 CPU/构建选项

pip install . -Csetup-args=-Dcpu-baseline="avx2 fma3" -Csetup-args=-Dcpu-dispatch="max"

快速入门#

通常,默认设置倾向于不强制要求某些在旧处理器上可能不可用的 CPU 特性。提高基线特性要求通常会改善性能,并可能减小二进制文件大小。

以下是可能需要更改默认设置的最常见场景

我正在为本地使用构建 NumPy#

并且我不打算将此构建版本导出给其他用户,也不针对与主机不同的 CPU。

为基线设置 native,或者在您的平台不支持 native 选项的情况下手动指定 CPU 特性

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

在这种情况下,使用额外的 CPU 特性构建 NumPy 是不必要的,因为所有支持的特性都已在基线特性中定义。

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

注意

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

我不想支持 x86 架构的旧处理器#

由于现在大多数 CPU 都至少支持 AVXF16C 特性,您可以使用

python -m build --wheel -Csetup-args=-Dcpu-baseline="avx f16c"

注意

cpu-baseline 会强制合并所有隐含特性,因此无需添加 SSE 特性。

我遇到与上述情况相同的问题,但使用的是 ppc64 架构#

那么将基线特性的上限提高到 Power8

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

AVX512 特性有问题?#

您可能对包含 AVX512 或任何其他 CPU 特性有所保留,并希望将其从调度特性中排除。

python -m build --wheel -Csetup-args=-Dcpu-dispatch="max -avx512f -avx512cd \
-avx512_knl -avx512_knm -avx512_skx -avx512_clx -avx512_cnl -avx512_icl -avx512_spr"

支持的特性#

特性名称可以表示一个特性或一组特性,如下表所示,支持情况取决于最低限度。

注意

以下特性可能不被所有编译器支持,此外,某些编译器在处理 AVX512AVX2FMA3 等特性时可能会生成不同的隐含特性集。更多详情请参阅 平台差异

在 x86 上#

名称

隐含

包含

SSE

SSE2

SSE2

SSE

SSE3

SSE SSE2

SSSE3

SSE SSE2 SSE3

SSE41

SSE SSE2 SSE3 SSSE3

POPCNT

SSE SSE2 SSE3 SSSE3 SSE41

SSE42

SSE SSE2 SSE3 SSSE3 SSE41 POPCNT

AVX

SSE SSE2 SSE3 SSSE3 SSE41 POPCNT SSE42

XOP

SSE SSE2 SSE3 SSSE3 SSE41 POPCNT SSE42 AVX

FMA4

SSE SSE2 SSE3 SSSE3 SSE41 POPCNT SSE42 AVX

F16C

SSE SSE2 SSE3 SSSE3 SSE41 POPCNT SSE42 AVX

FMA3

SSE SSE2 SSE3 SSSE3 SSE41 POPCNT SSE42 AVX F16C

AVX2

SSE SSE2 SSE3 SSSE3 SSE41 POPCNT SSE42 AVX F16C

AVX512F

SSE SSE2 SSE3 SSSE3 SSE41 POPCNT SSE42 AVX F16C FMA3 AVX2

AVX512CD

SSE SSE2 SSE3 SSSE3 SSE41 POPCNT SSE42 AVX F16C FMA3 AVX2 AVX512F

AVX512_KNL

SSE SSE2 SSE3 SSSE3 SSE41 POPCNT SSE42 AVX F16C FMA3 AVX2 AVX512F AVX512CD

AVX512ER AVX512PF

AVX512_KNM

SSE SSE2 SSE3 SSSE3 SSE41 POPCNT SSE42 AVX F16C FMA3 AVX2 AVX512F AVX512CD AVX512_KNL

AVX5124FMAPS AVX5124VNNIW AVX512VPOPCNTDQ

AVX512_SKX

SSE SSE2 SSE3 SSSE3 SSE41 POPCNT SSE42 AVX F16C FMA3 AVX2 AVX512F AVX512CD

AVX512VL AVX512BW AVX512DQ

AVX512_CLX

SSE SSE2 SSE3 SSSE3 SSE41 POPCNT SSE42 AVX F16C FMA3 AVX2 AVX512F AVX512CD AVX512_SKX

AVX512VNNI

AVX512_CNL

SSE SSE2 SSE3 SSSE3 SSE41 POPCNT SSE42 AVX F16C FMA3 AVX2 AVX512F AVX512CD AVX512_SKX

AVX512IFMA AVX512VBMI

AVX512_ICL

SSE SSE2 SSE3 SSSE3 SSE41 POPCNT SSE42 AVX F16C FMA3 AVX2 AVX512F AVX512CD AVX512_SKX AVX512_CLX AVX512_CNL

AVX512VBMI2 AVX512BITALG AVX512VPOPCNTDQ

AVX512_SPR

SSE SSE2 SSE3 SSSE3 SSE41 POPCNT SSE42 AVX F16C FMA3 AVX2 AVX512F AVX512CD AVX512_SKX AVX512_CLX AVX512_CNL AVX512_ICL

AVX512FP16

在 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

特殊选项#

  • NONE:不启用任何特性。

  • NATIVE:启用主机 CPU 支持的所有 CPU 特性,此操作基于编译器标志(-march=native, -xHost, /QxHost

  • MIN:启用可在广泛平台上安全运行的最低 CPU 特性。

    对于架构

    隐含

    x86 (32 位模式)

    SSE SSE2

    x86_64

    SSE SSE2 SSE3

    IBM/POWER (大端模式)

    NONE

    IBM/POWER (小端模式)

    VSX VSX2

    ARMHF

    NONE

    ARM64 即 AARCH64

    NEON NEON_FP16 NEON_VFPV4 ASIMD

    IBM/ZSYSTEM(S390X)

    NONE

  • MAX:启用编译器和平台支持的所有 CPU 特性。

  • Operators-/+:移除或添加特性,与 MAXMINNATIVE 选项结合使用时非常有用。

行为#

  • CPU 特性和其他选项不区分大小写,例如

    python -m build --wheel -Csetup-args=-Dcpu-dispatch="SSE41 avx2 FMA3"
    
  • 请求的优化顺序无关紧要

    python -m build --wheel -Csetup-args=-Dcpu-dispatch="SSE41 AVX2 FMA3"
    # equivalent to
    python -m build --wheel -Csetup-args=-Dcpu-dispatch="FMA3 AVX2 SSE41"
    
  • 逗号、空格或“+”都可以用作分隔符,例如

    python -m build --wheel -Csetup-args=-Dcpu-dispatch="avx2 avx512f"
    # or
    python -m build --wheel -Csetup-args=-Dcpu-dispatch=avx2,avx512f
    # or
    python -m build --wheel -Csetup-args=-Dcpu-dispatch="avx2+avx512f"
    

    所有方法都有效,但如果使用空格,参数应加引号或用反斜杠转义。

  • cpu-baseline 会合并所有隐含的 CPU 特性,例如

    python -m build --wheel -Csetup-args=-Dcpu-baseline=sse42
    # equivalent to
    python -m build --wheel -Csetup-args=-Dcpu-baseline="sse sse2 sse3 ssse3 sse41 popcnt sse42"
    
  • 如果通过环境变量 CFLAGS 启用了编译器原生标志 -march=native-xHost/QxHost,则 cpu-baseline 将被视为“原生”。

    export CFLAGS="-march=native"
    pip install .
    # is equivalent to
    pip install . -Csetup-args=-Dcpu-baseline=native
    
  • cpu-baseline 会跳过目标平台或编译器不支持的任何指定特性,而不是引发致命错误。

    注意

    由于 cpu-baseline 会合并所有隐含特性,因此将启用最大支持的隐含特性,而不是跳过所有这些特性。例如

    # Requesting `AVX2,FMA3` but the compiler only support **SSE** features
    python -m build --wheel -Csetup-args=-Dcpu-baseline="avx2 fma3"
    # is equivalent to
    python -m build --wheel -Csetup-args=-Dcpu-baseline="sse sse2 sse3 ssse3 sse41 popcnt sse42"
    
  • cpu-dispatch 不会合并任何隐含的 CPU 特性,因此除非您想禁用其中一个或全部特性,否则必须手动添加它们。

    # Only dispatches AVX2 and FMA3
    python -m build --wheel -Csetup-args=-Dcpu-dispatch=avx2,fma3
    # Dispatches AVX and SSE features
    python -m build --wheel -Csetup-args=-Dcpu-dispatch=ssse3,sse41,sse42,avx,avx2,fma3
    
  • cpu-dispatch 会跳过任何指定的基线特性,也会跳过目标平台或编译器不支持的任何特性,而不会引发致命错误。

最后,您应该始终通过构建日志检查最终报告,以验证启用的特性。更多详情请参阅 构建报告

平台差异#

在某些编译器或架构下,一些特殊情况迫使我们将某些特性关联在一起,导致无法单独构建它们。

这些条件可分为两部分,如下所示

架构兼容性

需要对齐相同架构的后续代次确定支持的某些 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 特性提供独立支持。例如,**Intel** 的编译器不为 AVX2FMA3 提供单独的标志,这是有道理的,因为所有支持 AVX2 的 Intel CPU 也支持 FMA3,但这种方法与来自 **AMD** 或 **VIA** 的其他 **x86** CPU 不兼容。

例如

# Specify AVX2 will force enables FMA3 on Intel compilers
python -m build --wheel -Csetup-args=-Dcpu-baseline=avx2
# which is equivalent to
python -m build --wheel -Csetup-args=-Dcpu-baseline="avx2 fma3"

以下表格仅显示了某些编译器在 支持的特性 表格中所示的一般上下文中强加的差异

注意

带删除线的特性名称表示不支持的 CPU 特性。

在 x86::Intel 编译器上#

名称

隐含

包含

FMA3

SSE SSE2 SSE3 SSSE3 SSE41 POPCNT SSE42 AVX F16C AVX2

AVX2

SSE SSE2 SSE3 SSSE3 SSE41 POPCNT SSE42 AVX F16C FMA3

AVX512F

SSE SSE2 SSE3 SSSE3 SSE41 POPCNT SSE42 AVX F16C FMA3 AVX2 AVX512CD

XOP

SSE SSE2 SSE3 SSSE3 SSE41 POPCNT SSE42 AVX

FMA4

SSE SSE2 SSE3 SSSE3 SSE41 POPCNT SSE42 AVX

AVX512_SPR

SSE SSE2 SSE3 SSSE3 SSE41 POPCNT SSE42 AVX F16C FMA3 AVX2 AVX512F AVX512CD AVX512_SKX AVX512_CLX AVX512_CNL AVX512_ICL

AVX512FP16

在 x86::Microsoft Visual C/C++ 上#

名称

隐含

包含

FMA3

SSE SSE2 SSE3 SSSE3 SSE41 POPCNT SSE42 AVX F16C AVX2

AVX2

SSE SSE2 SSE3 SSSE3 SSE41 POPCNT SSE42 AVX F16C FMA3

AVX512F

SSE SSE2 SSE3 SSSE3 SSE41 POPCNT SSE42 AVX F16C FMA3 AVX2 AVX512CD AVX512_SKX

AVX512CD

SSE SSE2 SSE3 SSSE3 SSE41 POPCNT SSE42 AVX F16C FMA3 AVX2 AVX512F AVX512_SKX

AVX512_KNL

SSE SSE2 SSE3 SSSE3 SSE41 POPCNT SSE42 AVX F16C FMA3 AVX2 AVX512F AVX512CD

AVX512ER AVX512PF

AVX512_KNM

SSE SSE2 SSE3 SSSE3 SSE41 POPCNT SSE42 AVX F16C FMA3 AVX2 AVX512F AVX512CD AVX512_KNL

AVX5124FMAPS AVX5124VNNIW AVX512VPOPCNTDQ

AVX512_SPR

SSE SSE2 SSE3 SSSE3 SSE41 POPCNT SSE42 AVX F16C FMA3 AVX2 AVX512F AVX512CD AVX512_SKX AVX512_CLX AVX512_CNL AVX512_ICL

AVX512FP16

构建报告#

在大多数情况下,CPU 构建选项不会产生任何导致构建挂起的致命错误。构建日志中可能出现的大多数错误都可视为严重的警告,这是因为编译器缺少一些预期的 CPU 特性。

因此,我们强烈建议您检查最终报告日志,以了解哪些 CPU 特性已启用,哪些未启用。

您可以在构建日志的末尾找到 CPU 优化最终报告,以下是其在 x86_64/gcc 上的样子

########### EXT COMPILER OPTIMIZATION ###########
Platform      :
  Architecture: x64
  Compiler    : gcc

CPU baseline  :
  Requested   : 'min'
  Enabled     : SSE SSE2 SSE3
  Flags       : -msse -msse2 -msse3
  Extra checks: none

CPU dispatch  :
  Requested   : 'max -xop -fma4'
  Enabled     : SSSE3 SSE41 POPCNT SSE42 AVX F16C FMA3 AVX2 AVX512F AVX512CD AVX512_KNL AVX512_KNM AVX512_SKX AVX512_CLX AVX512_CNL AVX512_ICL
  Generated   :
              :
  SSE41       : SSE SSE2 SSE3 SSSE3
  Flags       : -msse -msse2 -msse3 -mssse3 -msse4.1
  Extra checks: none
  Detect      : SSE SSE2 SSE3 SSSE3 SSE41
              : build/src.linux-x86_64-3.9/numpy/_core/src/umath/loops_arithmetic.dispatch.c
              : numpy/_core/src/umath/_umath_tests.dispatch.c
              :
  SSE42       : SSE SSE2 SSE3 SSSE3 SSE41 POPCNT
  Flags       : -msse -msse2 -msse3 -mssse3 -msse4.1 -mpopcnt -msse4.2
  Extra checks: none
  Detect      : SSE SSE2 SSE3 SSSE3 SSE41 POPCNT SSE42
              : build/src.linux-x86_64-3.9/numpy/_core/src/_simd/_simd.dispatch.c
              :
  AVX2        : SSE SSE2 SSE3 SSSE3 SSE41 POPCNT SSE42 AVX F16C
  Flags       : -msse -msse2 -msse3 -mssse3 -msse4.1 -mpopcnt -msse4.2 -mavx -mf16c -mavx2
  Extra checks: none
  Detect      : AVX F16C AVX2
              : build/src.linux-x86_64-3.9/numpy/_core/src/umath/loops_arithm_fp.dispatch.c
              : build/src.linux-x86_64-3.9/numpy/_core/src/umath/loops_arithmetic.dispatch.c
              : numpy/_core/src/umath/_umath_tests.dispatch.c
              :
  (FMA3 AVX2) : SSE SSE2 SSE3 SSSE3 SSE41 POPCNT SSE42 AVX F16C
  Flags       : -msse -msse2 -msse3 -mssse3 -msse4.1 -mpopcnt -msse4.2 -mavx -mf16c -mfma -mavx2
  Extra checks: none
  Detect      : AVX F16C FMA3 AVX2
              : build/src.linux-x86_64-3.9/numpy/_core/src/_simd/_simd.dispatch.c
              : build/src.linux-x86_64-3.9/numpy/_core/src/umath/loops_exponent_log.dispatch.c
              : build/src.linux-x86_64-3.9/numpy/_core/src/umath/loops_trigonometric.dispatch.c
              :
  AVX512F     : SSE SSE2 SSE3 SSSE3 SSE41 POPCNT SSE42 AVX F16C FMA3 AVX2
  Flags       : -msse -msse2 -msse3 -mssse3 -msse4.1 -mpopcnt -msse4.2 -mavx -mf16c -mfma -mavx2 -mavx512f
  Extra checks: AVX512F_REDUCE
  Detect      : AVX512F
              : build/src.linux-x86_64-3.9/numpy/_core/src/_simd/_simd.dispatch.c
              : build/src.linux-x86_64-3.9/numpy/_core/src/umath/loops_arithm_fp.dispatch.c
              : build/src.linux-x86_64-3.9/numpy/_core/src/umath/loops_arithmetic.dispatch.c
              : build/src.linux-x86_64-3.9/numpy/_core/src/umath/loops_exponent_log.dispatch.c
              : build/src.linux-x86_64-3.9/numpy/_core/src/umath/loops_trigonometric.dispatch.c
              :
  AVX512_SKX  : SSE SSE2 SSE3 SSSE3 SSE41 POPCNT SSE42 AVX F16C FMA3 AVX2 AVX512F AVX512CD
  Flags       : -msse -msse2 -msse3 -mssse3 -msse4.1 -mpopcnt -msse4.2 -mavx -mf16c -mfma -mavx2 -mavx512f -mavx512cd -mavx512vl -mavx512bw -mavx512dq
  Extra checks: AVX512BW_MASK AVX512DQ_MASK
  Detect      : AVX512_SKX
              : build/src.linux-x86_64-3.9/numpy/_core/src/_simd/_simd.dispatch.c
              : build/src.linux-x86_64-3.9/numpy/_core/src/umath/loops_arithmetic.dispatch.c
              : build/src.linux-x86_64-3.9/numpy/_core/src/umath/loops_exponent_log.dispatch.c
CCompilerOpt.cache_flush[804] : write cache to path -> /home/seiko/work/repos/numpy/build/temp.linux-x86_64-3.9/ccompiler_opt_cache_ext.py

########### CLIB COMPILER OPTIMIZATION ###########
Platform      :
  Architecture: x64
  Compiler    : gcc

CPU baseline  :
  Requested   : 'min'
  Enabled     : SSE SSE2 SSE3
  Flags       : -msse -msse2 -msse3
  Extra checks: none

CPU dispatch  :
  Requested   : 'max -xop -fma4'
  Enabled     : SSSE3 SSE41 POPCNT SSE42 AVX F16C FMA3 AVX2 AVX512F AVX512CD AVX512_KNL AVX512_KNM AVX512_SKX AVX512_CLX AVX512_CNL AVX512_ICL
  Generated   : none

build_extbuild_clib 各有一个单独的报告,其中包含多个部分,每个部分有多个值,表示以下内容

平台:

  • 架构:目标 CPU 的架构名称。应为 x86, x64, ppc64, ppc64le, armhf, aarch64, s390xunknown 之一。

  • 编译器:编译器名称。应为 gcc, clang, msvc, icc, iccw 或类 Unix 之一。

CPU 基线:

  • 请求cpu-baseline 的具体特性和选项(原样)。

  • 已启用:最终启用的 CPU 特性集。

  • 标志:编译期间用于所有 NumPy C/C++ 源文件的编译器标志,但用于生成调度特性二进制对象的临时源文件除外。

  • 额外检查:内部检查列表,用于激活与已启用特性相关的某些功能或内在函数,在开发 SIMD 内核时有助于调试。

CPU 调度:

  • 请求cpu-dispatch 的具体特性和选项(原样)。

  • 已启用:最终启用的 CPU 特性集。

  • 已生成:在此属性的下一行开头,显示了已生成优化特性的形式,分为几个部分,其属性解释如下

    • 一个或多个调度特性:隐含的 CPU 特性。

    • 标志:用于这些特性的编译器标志。

    • 额外检查:与基线类似,但针对这些调度特性。

    • 检测:在运行时需要检测的 CPU 特性集,以便执行生成的优化。

    • 上述属性之后以“:”在单独一行结尾的行,表示定义生成优化的 C/C++ 源文件路径。

运行时调度#

导入 NumPy 会触发对可调度特性集中可用 CPU 特性的扫描。可以通过将环境变量 NPY_DISABLE_CPU_FEATURES 设置为逗号、制表符或空格分隔的要禁用特性列表来进一步限制此操作。如果解析失败或特性未启用,这将引发错误。例如,在 x86_64 上,这将禁用 AVX2FMA3

NPY_DISABLE_CPU_FEATURES="AVX2,FMA3"

如果该特性不可用,将发出警告。

跟踪调度函数#

通过 Python 函数 numpy.lib.introspect.opt_func_info 可以发现不同优化函数启用了哪些 CPU 目标。此函数提供了使用两个可选参数应用过滤器的灵活性:一个用于精炼函数名称,另一个用于指定签名中的数据类型。

例如

 >> 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": "SSE41",
       "available": "SSE41 baseline(SSE SSE2 SSE3)"
     },
     "Ff": {
       "current": "FMA3__AVX2",
       "available": "AVX512F FMA3__AVX2 baseline(SSE SSE2 SSE3)"
     },
     "Dd": {
       "current": "FMA3__AVX2",
       "available": "AVX512F FMA3__AVX2 baseline(SSE SSE2 SSE3)"
     }
   },
   "add": {
     "ddd": {
       "current": "FMA3__AVX2",
       "available": "FMA3__AVX2 baseline(SSE SSE2 SSE3)"
     },
     "FFF": {
       "current": "FMA3__AVX2",
       "available": "FMA3__AVX2 baseline(SSE SSE2 SSE3)"
     }
  }
}