torch.utils.cpp_extension#
创建于:2018年3月7日 | 最后更新于:2025年2月16日
- torch.utils.cpp_extension.CppExtension(name, sources, *args, **kwargs)[源代码]#
创建一个用于 C++ 的
setuptools.Extension。方便的方法,用于创建一个具有最少(但通常足够)参数的
setuptools.Extension,以构建 C++ 扩展。所有参数都会转发到
setuptools.Extension构造函数。完整的参数列表可在 https://setuptools.pypa.io/en/latest/userguide/ext_modules.html#extension-api-reference 找到。警告
PyTorch 的 Python API(如 libtorch_python 中提供)不能使用
py_limited_api=True标志进行构建。当传递此标志时,用户有责任在其库中不使用 libtorch_python (尤其是 pytorch/python 绑定) 中的 API,而只使用 libtorch (aten 对象、运算符和分发器) 中的 API。例如,要从 Python 访问自定义操作,库应通过分发器注册这些操作。与 CPython setuptools 不同,CPython setuptools 在
setup中将 py_limited_api 指定为 "bdist_wheel" 命令的选项时,不会将 -DPy_LIMITED_API 定义为编译标志,而 PyTorch 会!我们将指定 -DPy_LIMITED_API=min_supported_cpython 以最好地强制执行一致性、安全性和合理性,从而鼓励最佳实践。要针对不同的版本,请将 min_supported_cpython 设置为所选 CPython 版本的十六进制代码。示例
>>> from setuptools import setup >>> from torch.utils.cpp_extension import BuildExtension, CppExtension >>> setup( ... name='extension', ... ext_modules=[ ... CppExtension( ... name='extension', ... sources=['extension.cpp'], ... extra_compile_args=['-g'], ... extra_link_args=['-Wl,--no-as-needed', '-lm']) ... ], ... cmdclass={ ... 'build_ext': BuildExtension ... })
- torch.utils.cpp_extension.CUDAExtension(name, sources, *args, **kwargs)[源代码]#
创建一个用于 CUDA/C++ 的
setuptools.Extension。方便的方法,用于创建一个具有最少(但通常足够)参数的
setuptools.Extension,以构建 CUDA/C++ 扩展。这包括 CUDA 的包含路径、库路径和运行时库。所有参数都会转发到
setuptools.Extension构造函数。完整的参数列表可在 https://setuptools.pypa.io/en/latest/userguide/ext_modules.html#extension-api-reference 找到。警告
PyTorch 的 Python API(如 libtorch_python 中提供)不能使用
py_limited_api=True标志进行构建。当传递此标志时,用户有责任在其库中不使用 libtorch_python (尤其是 pytorch/python 绑定) 中的 API,而只使用 libtorch (aten 对象、运算符和分发器) 中的 API。例如,要从 Python 访问自定义操作,库应通过分发器注册这些操作。与 CPython setuptools 不同,CPython setuptools 在
setup中将 py_limited_api 指定为 "bdist_wheel" 命令的选项时,不会将 -DPy_LIMITED_API 定义为编译标志,而 PyTorch 会!我们将指定 -DPy_LIMITED_API=min_supported_cpython 以最好地强制执行一致性、安全性和合理性,从而鼓励最佳实践。要针对不同的版本,请将 min_supported_cpython 设置为所选 CPython 版本的十六进制代码。示例
>>> from setuptools import setup >>> from torch.utils.cpp_extension import BuildExtension, CUDAExtension >>> setup( ... name='cuda_extension', ... ext_modules=[ ... CUDAExtension( ... name='cuda_extension', ... sources=['extension.cpp', 'extension_kernel.cu'], ... extra_compile_args={'cxx': ['-g'], ... 'nvcc': ['-O2']}, ... extra_link_args=['-Wl,--no-as-needed', '-lcuda']) ... ], ... cmdclass={ ... 'build_ext': BuildExtension ... })
计算能力
默认情况下,扩展将编译为在构建过程中可见的所有显卡上运行,以及 PTX。如果将来安装了新显卡,则可能需要重新编译扩展。如果可见显卡的计算能力 (CC) 比 nvcc 可构建完全编译的二进制文件的最新版本新,PyTorch 将使 nvcc 回退到使用 nvcc 支持的最新 PTX 版本进行内核构建(有关 PTX 的详细信息,请参阅下文)。
您可以使用 TORCH_CUDA_ARCH_LIST 覆盖默认行为,以明确指定您希望扩展支持的 CC。
TORCH_CUDA_ARCH_LIST="6.1 8.6" python build_my_extension.pyTORCH_CUDA_ARCH_LIST="5.2 6.0 6.1 7.0 7.5 8.0 8.6+PTX" python build_my_extension.py+PTX 选项会导致扩展内核二进制文件包含指定 CC 的 PTX 指令。PTX 是一种中间表示,它允许内核为任何 CC >= 指定 CC 进行运行时编译(例如,8.6+PTX 生成的 PTX 可以为任何 CC >= 8.6 的 GPU 进行运行时编译)。这可以提高二进制文件的前向兼容性。然而,依赖较旧的 PTX 通过运行时编译为较新的 CC 来提供前向兼容性,可能会在中度降低这些较新 CC 的性能。如果您知道要定位的 GPU 的确切 CC,最好单独指定它们。例如,如果您希望您的扩展在 8.0 和 8.6 上运行,“8.0+PTX”在功能上可以工作,因为它包含可以为 8.6 运行时编译的 PTX,但“8.0 8.6”会更好。
请注意,虽然可以包含所有支持的架构,但包含的架构越多,构建过程就会越慢,因为它将为每个架构构建一个单独的内核映像。
注意:CUDA-11.5 nvcc 在 Windows 上解析 torch/extension.h 时会遇到内部编译器错误。为解决此问题,请将 Python 绑定逻辑移至纯 C++ 文件。
- 示例用法
#include <ATen/ATen.h> at::Tensor SigmoidAlphaBlendForwardCuda(….)
- 而不是
#include <torch/extension.h> torch::Tensor SigmoidAlphaBlendForwardCuda(…)
当前 nvcc 错误开放问题:pytorch/pytorch#69460 完整的解决方法代码示例:facebookresearch/pytorch3d
可重定位设备代码链接
如果您想在编译单元之间(对象文件之间)引用设备符号,则需要使用 可重定位设备代码 (-rdc=true 或 -dc) 构建对象文件。此规则的一个例外是“动态并行”(嵌套内核启动),它现在已不太常用。 可重定位设备代码 优化程度较低,因此应仅用于需要它的对象文件。在设备代码编译步骤和 dlink 步骤中使用 -dlto(设备链接时优化)有助于减少 -rdc 对性能的潜在下降。请注意,它需要在两个步骤中都使用才有意义。
如果您有 rdc 对象,则需要在 CPU 符号链接步骤之前执行额外的 -dlink(设备链接)步骤。在不使用 -rdc 的情况下使用 -dlink 的情况也有:当扩展链接到一个包含 rdc 编译对象的静态库时,例如 [NVSHMEM 库](https://developer.nvidia.com/nvshmem)。
注意:使用 RDC 链接构建 CUDA 扩展需要 Ninja。
示例
>>> CUDAExtension( ... name='cuda_extension', ... sources=['extension.cpp', 'extension_kernel.cu'], ... dlink=True, ... dlink_libraries=["dlink_lib"], ... extra_compile_args={'cxx': ['-g'], ... 'nvcc': ['-O2', '-rdc=true']})
- torch.utils.cpp_extension.SyclExtension(name, sources, *args, **kwargs)[源代码]#
创建一个用于 SYCL/C++ 的
setuptools.Extension。方便的方法,用于创建一个具有最少(但通常足够)参数的
setuptools.Extension,以构建 SYCL/C++ 扩展。所有参数都会转发到
setuptools.Extension构造函数。警告
PyTorch 的 Python API(如 libtorch_python 中提供)不能使用
py_limited_api=True标志进行构建。当传递此标志时,用户有责任在其库中不使用 libtorch_python (尤其是 pytorch/python 绑定) 中的 API,而只使用 libtorch (aten 对象、运算符和分发器) 中的 API。例如,要从 Python 访问自定义操作,库应通过分发器注册这些操作。与 CPython setuptools 不同,CPython setuptools 在
setup中将 py_limited_api 指定为 "bdist_wheel" 命令的选项时,不会将 -DPy_LIMITED_API 定义为编译标志,而 PyTorch 会!我们将指定 -DPy_LIMITED_API=min_supported_cpython 以最好地强制执行一致性、安全性和合理性,从而鼓励最佳实践。要针对不同的版本,请将 min_supported_cpython 设置为所选 CPython 版本的十六进制代码。示例
>>> from torch.utils.cpp_extension import BuildExtension, SyclExtension >>> setup( ... name='xpu_extension', ... ext_modules=[ ... SyclExtension( ... name='xpu_extension', ... sources=['extension.cpp', 'extension_kernel.cpp'], ... extra_compile_args={'cxx': ['-g', '-std=c++20', '-fPIC']}) ... ], ... cmdclass={ ... 'build_ext': BuildExtension ... })
默认情况下,扩展将编译为在构建过程中可见的所有设备的架构上运行。如果将来安装了新设备,则可能需要重新编译扩展。您可以使用 TORCH_XPU_ARCH_LIST 覆盖默认行为,以明确指定您希望扩展支持的设备架构。
TORCH_XPU_ARCH_LIST="pvc,xe-lpg" python build_my_extension.py请注意,虽然可以包含所有支持的架构,但包含的架构越多,构建过程就会越慢,因为它将为每个架构构建一个单独的内核映像。
注意:构建 SyclExtension 需要 Ninja。
- torch.utils.cpp_extension.BuildExtension(*args, **kwargs)[源代码]#
一个自定义的
setuptools构建扩展。这个
setuptools.build_ext子类负责传递最低要求的编译器标志(例如-std=c++17)以及混合 C++/CUDA/SYCL 编译(以及对 CUDA/SYCL 文件的一般支持)。当使用
BuildExtension时,允许为extra_compile_args提供一个字典(而不是通常的列表),该字典将语言/编译器(唯一预期的值是cxx、nvcc或sycl)映射到要传递给编译器的附加编译器标志列表。这使得在混合编译期间可以为 C++、CUDA 和 SYCL 编译器提供不同的标志。use_ninja(bool):如果use_ninja为True(默认),则我们尝试使用 Ninja 后端进行构建。与标准的setuptools.build_ext相比,Ninja 大大加快了编译速度。如果 Ninja 不可用,则回退到标准的 distutils 后端。注意
默认情况下,Ninja 后端使用 #CPUS + 2 个工作进程来构建扩展。这可能会在某些系统上占用过多资源。可以通过将 MAX_JOBS 环境变量设置为非负数来控制工作进程的数量。
- torch.utils.cpp_extension.load(name, sources, extra_cflags=None, extra_cuda_cflags=None, extra_sycl_cflags=None, extra_ldflags=None, extra_include_paths=None, build_directory=None, verbose=False, with_cuda=None, with_sycl=None, is_python_module=True, is_standalone=False, keep_intermediates=True)[源代码]#
即时(JIT)加载 PyTorch C++ 扩展。
要加载扩展,会生成一个 Ninja 构建文件,该文件用于将给定的源文件编译成动态库。然后,该库将被加载到当前的 Python 进程中作为一个模块,并从此函数返回,准备使用。
默认情况下,生成构建文件并从中编译生成库的目录是
<tmp>/torch_extensions/<name>,其中<tmp>是当前平台上的临时文件夹,而<name>是扩展的名称。此位置可以通过两种方式覆盖。首先,如果设置了TORCH_EXTENSIONS_DIR环境变量,它将替换<tmp>/torch_extensions,所有扩展将编译到此目录的子文件夹中。其次,如果提供了此函数的build_directory参数,它将完全覆盖路径,即库将直接编译到该文件夹中。要编译源文件,将使用系统默认编译器(
c++),可以通过设置CXX环境变量来覆盖。要将其他参数传递给编译过程,可以提供extra_cflags或extra_ldflags。例如,要使用优化编译您的扩展,请传递extra_cflags=['-O3']。您还可以使用extra_cflags来传递其他包含目录。提供了 CUDA 支持和混合编译。只需将 CUDA 源文件(
.cu或.cuh)与其它源文件一起传递。这些文件将被检测到并使用 nvcc 而不是 C++ 编译器进行编译。这包括将 CUDA lib64 目录作为库目录传递,并链接cudart。您可以通过extra_cuda_cflags向 nvcc 传递其他标志,就像对 C++ 使用extra_cflags一样。使用了各种查找 CUDA 安装目录的启发式方法,通常都能正常工作。如果不行,设置CUDA_HOME环境变量是最安全的选择。提供了 SYCL 支持和混合编译。只需将 SYCL 源文件(
.sycl)与其它源文件一起传递。这些文件将被检测到并使用 SYCL 编译器(例如 Intel DPC++ Compiler)而不是 C++ 编译器进行编译。您可以将其他标志通过extra_sycl_cflags传递给 SYCL 编译器,就像对 C++ 使用extra_cflags一样。SYCL 编译器预计可以通过系统 PATH 环境变量找到。- 参数
name – 要构建的扩展的名称。这必须与 pybind11 模块的名称相同!
extra_cflags – 要转发给构建的可选编译器标志列表。
extra_cuda_cflags – 在构建 CUDA 源文件时要转发给 nvcc 的可选编译器标志列表。
extra_sycl_cflags – 在构建 SYCL 源文件时要转发给 SYCL 编译器的可选编译器标志列表。
extra_ldflags – 要转发给构建的可选链接器标志列表。
extra_include_paths – 要转发给构建的可选包含目录列表。
build_directory – 用于作为构建工作区的可选路径。
verbose – 如果为
True,则打开加载步骤的详细日志记录。with_cuda(Optional[bool])– 确定是否将 CUDA 头文件和库添加到构建中。如果设置为
None(默认),此值将根据sources中是否存在.cu或.cuh自动确定。将其设置为 True` 以强制包含 CUDA 头文件和库。with_sycl(Optional[bool])– 确定是否将 SYCL 头文件和库添加到构建中。如果设置为
None(默认),此值将根据sources中是否存在.sycl自动确定。将其设置为 True` 以强制包含 SYCL 头文件和库。is_python_module – 如果为
True(默认),则将生成的共享库导入为 Python 模块。如果为False,则行为取决于is_standalone。is_standalone – 如果为
False(默认),则将构造的扩展加载到进程中作为普通的动态库。如果为True,则构建一个独立的 C++ 可执行文件。
- 返回
返回加载的 PyTorch 扩展作为 Python 模块。
- 如果
is_python_module为False且is_standalone为False 不返回任何内容。(共享库已作为副作用加载到进程中。)
- 如果
is_standalone为True。 返回可执行文件的路径。(在 Windows 上,TORCH_LIB_PATH 作为副作用添加到 PATH 环境变量中。)
- 如果
- 返回类型
如果
is_python_module为True
示例
>>> from torch.utils.cpp_extension import load >>> module = load( ... name='extension', ... sources=['extension.cpp', 'extension_kernel.cu'], ... extra_cflags=['-O2'], ... verbose=True)
- torch.utils.cpp_extension.load_inline(name, cpp_sources, cuda_sources=None, sycl_sources=None, functions=None, extra_cflags=None, extra_cuda_cflags=None, extra_sycl_cflags=None, extra_ldflags=None, extra_include_paths=None, build_directory=None, verbose=False, with_cuda=None, with_sycl=None, is_python_module=True, with_pytorch_error_handling=True, keep_intermediates=True, use_pch=False, no_implicit_headers=False)[源代码]#
从字符串源即时(JIT)加载 PyTorch C++ 扩展。
此函数与
load()的行为完全相同,但它将源作为字符串而不是文件名接收。这些字符串将被写入构建目录中的文件,之后load_inline()的行为与load()相同。请参阅 tests 以获取使用此函数的良好示例。
源文件可以省略典型非内联 C++ 扩展的两个必需部分:必要的头文件包含,以及(pybind11)绑定代码。更具体地说,传递给
cpp_sources的字符串首先被连接成一个单独的.cpp文件。然后,在此文件前添加#include <torch/extension.h>。此外,如果提供了
functions参数,则会自动为每个指定的函数生成绑定。functions可以是函数名列表,也可以是从函数名映射到文档字符串的字典。如果给出了列表,则每个函数的名称将用作其文档字符串。cuda_sources中的源文件被连接成一个单独的.cu文件,并在前面添加torch/types.h、cuda.h和cuda_runtime.h包含。.cpp和.cu文件分别编译,但最终链接成一个库。请注意,cuda_sources中的函数本身不会生成绑定。要绑定到 CUDA 内核,您必须创建一个调用它的 C++ 函数,并在cpp_sources中的一个文件中声明或定义此 C++ 函数(并将其名称包含在functions中)。sycl_sources中的源文件被连接成一个单独的.sycl文件,并在前面添加torch/types.h、sycl/sycl.hpp包含。.cpp和.sycl文件分别编译,但最终链接成一个库。请注意,sycl_sources中的函数本身不会生成绑定。要绑定到 SYCL 内核,您必须创建一个调用它的 C++ 函数,并在cpp_sources中的一个文件中声明或定义此 C++ 函数(并将其名称包含在functions中)。有关下面省略的参数的说明,请参阅
load()。- 参数
cpp_sources – 包含 C++ 源代码的字符串或字符串列表。
cuda_sources – 包含 CUDA 源代码的字符串或字符串列表。
sycl_sources – 包含 SYCL 源代码的字符串或字符串列表。
functions – 要为其生成函数绑定的函数名称列表。如果提供了字典,则应将函数名称映射到文档字符串(否则为函数名称本身)。
with_cuda – 确定是否将 CUDA 头文件和库添加到构建中。如果设置为
None(默认),此值将根据是否提供了cuda_sources自动确定。将其设置为True以强制包含 CUDA 头文件和库。with_sycl – 确定是否将 SYCL 头文件和库添加到构建中。如果设置为
None(默认),此值将根据是否提供了sycl_sources自动确定。将其设置为True以强制包含 SYCL 头文件和库。with_pytorch_error_handling – 确定是让 pytorch 宏(错误和警告)由 pytorch 而不是 pybind 进行处理。为此,每个函数
foo都通过一个中间函数_safe_foo调用。这种重定向在某些晦涩的 C++ 情况中可能会引起问题。当此重定向引起问题时,应将此标志设置为False。no_implicit_headers – 如果为
True,则跳过自动添加头文件,特别是#include <torch/extension.h>和#include <torch/types.h>行。当您已经在源代码中包含了必要的头文件时,使用此选项可以提高冷启动时间。默认值:False。
示例
>>> from torch.utils.cpp_extension import load_inline >>> source = """ at::Tensor sin_add(at::Tensor x, at::Tensor y) { return x.sin() + y.sin(); } """ >>> module = load_inline(name='inline_extension', ... cpp_sources=[source], ... functions=['sin_add'])
注意
由于 load_inline 将即时编译源代码,请确保您在运行时环境中安装了正确的工具链。例如,在加载 C++ 时,请确保 C++ 编译器可用。如果您正在加载 CUDA 扩展,您还需要另外安装相应的 CUDA 工具包(nvcc 和您的代码可能具有的任何其他依赖项)。编译工具链在安装 torch 时不包含,并且必须另外安装。
在编译过程中,默认情况下,Ninja 后端使用 #CPUS + 2 个工作进程来构建扩展。这可能会在某些系统上占用过多资源。可以通过将 MAX_JOBS 环境变量设置为非负数来控制工作进程的数量。
- torch.utils.cpp_extension.get_compiler_abi_compatibility_and_version(compiler)[源代码]#
确定给定的编译器是否与 PyTorch 兼容 ABI,以及其版本。