升级指南#

本页面涵盖了每个主要版本中引入的更改,用户在从旧版本迁移时应了解这些更改。另请参阅 兼容性矩阵 以了解每个主要版本支持的环境。

CuPy v13#

现代化的 CCCL 支持和需求#

NVIDIA 的 CUDA C++ 核心库 (CCCL) 是 Thrust、CUB 和 libcu++ 这些相互依赖的 C++ 库的新家,这些库随 CUDA Toolkit 11.0+ 一起发布。为了更好地服务于我们的用户,提供最新的 CCCL 功能、改进和错误修复,从 CuPy v13 开始,我们在 CuPy 的源代码和二进制(pip/conda)发布中捆绑了 CCCL。在构建时(用于构建 CuPy)和运行时(用于 JIT 编译内核)使用相同版本的 CCCL。这确保了行为的一致性,避免了意外情况,并允许如 CCCL 所承诺的双重 CUDA 支持(目前为 CUDA 11 和 12),但这一变化导致了以下与过去版本不同的后果:

  • 升级后,执行某些 CuPy 功能的第一次可能会比平时花费更长时间;

  • 现在,在构建或运行时,故意忽略来自任何本地CUDA安装的CCCL。

  • 想要尝试本地CCCL更改的冒险用户需要更新CCCL子模块并从源代码构建CuPy;

由于这一变化,CuPy 现在遵循与 CCCL(以及 CUDA Toolkit)相同的编译器要求,并将 C++11 作为最低的 C++ 标准。CCCL 预计在不久的将来会迁移到 C++17。

需求变更#

以下版本在 CuPy v13 中不再支持:

  • CUDA 11.1 或更早版本

  • cuDNN 8.7 或更早版本

  • cuTENSOR 1.x
    • 从 CuPy v13 开始添加了对 cuTENSOR 2.0 的支持,并将放弃对 cuTENSOR 1.x 的支持。这是因为从 cuTENSOR 1.x 到 2.0 有重大的 API 变化,从维护的角度来看,同时支持 cuTENSOR 1.x 和 2.0 API 是不切实际的。

  • Python 3.8 或更早版本

  • NumPy 1.21 或更早版本

  • Ubuntu 18.04

NumPy/SciPy 基线 API 更新#

Baseline API 已从 NumPy 1.24 和 SciPy 1.9 升级到 NumPy 1.26 和 SciPy 1.11。CuPy v13 将遵循这些基线版本的上游产品规范。

更改 cupy.asnumpy()/cupy.ndarray.get() 行为#

当将一个 CuPy 数组从 GPU 传输到 CPU(作为 NumPy 数组)时,以前在非默认流使用时,传输可能是非阻塞的,并且顺序不正确,如果在复制开始后立即在主机上修改结果数组,可能会导致潜在的数据竞争。在 CuPy v13 中,默认行为更改为始终阻塞,并添加了一个新的可选参数 blocking,如果设置为 False,则允许以前的非阻塞行为,在这种情况下,用户负责确保适当的流顺序。

更改 cupy.array()/cupy.asarray()/cupy.asanyarray() 行为#

当将一个 NumPy 数组从 CPU 传输到 GPU 时,以前即使源数组是由固定内存支持的,传输也总是阻塞的。在 CuPy v13 中,如果源数组被分配为固定内存,默认行为更改为异步以提高性能。

新增了一个可选参数 blocking,如果设置为 True,则允许之前的阻塞行为。如果有可能在传输完成之前在 CPU 上覆盖源数组,您可能希望设置此选项。

移除 cupy-wheel#

cupy-wheel 包,旨在作为一个“元”包,为用户环境选择并安装合适的 CuPy 二进制包,已在 CuPy v13 中被移除。这是因为最近的 Pip 不再允许动态更改需求。详情请参见 #7628

API 变更#

  • 一个 内部且未记录 的 API cupy.cuda.compile_with_cache(),在 CuPy v10 中被标记为弃用,现已被移除。我们鼓励下游库和用户迁移到使用公共 API,例如 RawKernel`(在 CuPy v5 中添加)。请参阅 :doc:./user_guide/kernel` 获取它们的教程。

CUDA Runtime API 现在被静态链接#

CuPy 现在与 CUDA Runtime 静态链接。因此,cupy.cuda.runtime.runtimeGetVersion() 总是返回 CuPy 构建时使用的 CUDA Runtime 版本,无论本地安装的 CUDA Runtime 版本如何。如果你需要检索本地安装的 CUDA Runtime 共享库的版本,请改用 cupy.cuda.get_local_runtime_version()

Docker 镜像更新#

CuPy 官方 Docker 镜像(详见 安装)现已更新以使用 CUDA 12.2。

CuPy v12#

更改 cupy.cuda.Device 行为#

CUDA 当前设备(通过 cupy.cuda.Device.use()cudaSetDevice() 设置)将在退出设备上下文管理器时重新激活。这将恢复 CuPy v10 中引入的更改,使得行为与 CuPy v9 或更早版本中的行为相同。

此决策是为了更好地与其他可能改变当前CUDA设备的库进行互操作性。假设有以下代码:

def do_preprocess_cupy():
    with cupy.cuda.Device(2):
        # ...
        pass

torch.cuda.set_device(1)
do_preprocess_cupy()
print(torch.cuda.get_device())  # -> ???

在 CuPy v10 和 v11 中,代码打印 0,这可能会让用户感到意外。在 CuPy v12 中,代码现在打印 1,使得用户和库开发者在使用多个设备时更容易维护当前设备。

弃用 cupy.ndarray.scatter_{add,max,min}#

这些API已被标记为弃用,因为 cupy.{add,maximum,minimum}.at ufunc 方法已经实现,其行为与等效且兼容NumPy。

需求变更#

以下版本在 CuPy v12 中不再支持:

  • Python 3.7 或更早版本

  • NumPy 1.20 或更早版本

  • SciPy 1.6 或更早版本

Baseline API 更新#

Baseline API 已从 NumPy 1.23 和 SciPy 1.8 升级到 NumPy 1.24 和 SciPy 1.9。CuPy v12 将遵循这些基线版本的上游产品规范。

Docker 镜像更新#

CuPy 官方 Docker 镜像(详见 安装)现已更新以使用 CUDA 11.8。

CuPy v11#

CUDA 11.2+ 的统一二进制包#

CuPy v11 提供了一个统一的二进制包,名为 cupy-cuda11x,它支持所有 CUDA 11.2+ 版本。这取代了按 CUDA 版本划分的二进制包(cupy-cuda112cupy-cuda117)。

请注意,CUDA 11.1 或更早版本仍然需要每个CUDA版本的二进制包。分别为CUDA 10.2、11.0和11.1提供``cupy-cuda102``、cupy-cuda110``和``cupy-cuda111

需求变更#

以下版本在 CuPy v11 中不再支持:

  • ROCm 4.2 或更早版本

  • NumPy 1.19 或更早版本

  • SciPy 1.5 或更早版本

默认启用CUB#

CuPy v11 默认通过 CUB 加速计算。如果需要,您可以通过将 CUPY_ACCELERATORS 环境变量设置为 "" 来关闭它。

Baseline API 更新#

Baseline API 已从 NumPy 1.21 和 SciPy 1.7 升级到 NumPy 1.23 和 SciPy 1.8。CuPy v11 将遵循这些基线版本的上游产品规范。

Docker 镜像更新#

CuPy 官方 Docker 镜像(详见 安装)现已更新,使用 CUDA 11.7 和 ROCm 5.0。

CuPy v10#

放弃对 CUDA 9.2 / 10.0 / 10.1 的支持#

不再支持 CUDA 10.1 或更早版本。请使用 CUDA 10.2 或更高版本。

放弃对 NCCL v2.4 / v2.6 / v2.7 的支持#

NCCL v2.4、v2.6 和 v2.7 不再受支持。

放弃对 Python 3.6 的支持#

Python 3.6 不再受支持。

放弃对 NumPy 1.17 的支持#

NumPy 1.17 不再受支持。

更改 cupy.cuda.Device 行为#

通过 use() 设置的当前设备在 with Device 块中将不被遵守#

备注

此更改已在 CuPy v12 中恢复。详情请参见上文的 CuPy v12 部分。

通过 cupy.cuda.Device.use() 设置的当前设备在退出设备上下文管理器时不会被重新激活。混合使用 with device: 块和 device.use() 的现有代码在 CuPy v10 和 v9 之间可能会得到不同的结果。

cupy.cuda.Device(1).use()
with cupy.cuda.Device(0):
    pass
cupy.cuda.Device()  # -> CuPy v10 returns device 0 instead of device 1

这一决定是为了更好地服务于 CuPy 用户,但它可能会对依赖于 CuPy 的下游 开发者 造成意外,因为本质上 CuPy 的 Device 上下文管理器不再遵循 CUDA 的 cudaSetDevice() API。不鼓励混合使用来自不同库的设备管理功能(特别是使用上下文管理器)。

对于仍然希望尊重 cudaGetDevice()/cudaSetDevice() API 的下游库,您应避免使用 with Device 上下文管理器来管理当前设备,而是应显式调用这些 API,例如参见 cupy/cupy#5963

cupy.cuda.Stream 行为中的变化#

流现在按设备管理#

以前,保持当前流与当前 CUDA 设备一致是用户的责任。例如,以下代码在 CuPy v9 或更早版本中会引发错误:

import cupy

with cupy.cuda.Device(0):
    # Create a stream on device 0.
    s0 = cupy.cuda.Stream()

with cupy.cuda.Device(1):
    with s0:
        # Try to use the stream on device 1
        cupy.arange(10)  # -> CUDA_ERROR_INVALID_HANDLE: invalid resource handle

CuPy v10 为每个设备管理当前流,从而消除了每次更改活动设备时切换流的需要。当使用 CuPy v10 时,上述示例的行为会有所不同,因为每当创建一个流时,它都会自动与当前设备关联,并且在切换设备时将被忽略。在早期版本中,尝试在设备 1 中使用 s0 会引发错误,因为 s0 与设备 0 关联。然而,在 v10 中,这个 s0 将被忽略,并且将使用设备 1 的默认流。

通过 use() 设置的当前流在退出 with 块时不会被恢复。#

与上述 cupy.cuda.Device 的更改相同,通过 cupy.cuda.Stream.use() 设置的当前流在退出流上下文管理器时不会被重新激活。混合使用 with stream: 块和 stream.use() 的现有代码在 CuPy v10 和 v9 之间可能会得到不同的结果。

s1 = cupy.cuda.Stream()
s2 = cupy.cuda.Stream()
s3 = cupy.cuda.Stream()
with s1:
    s2.use()
    with s3:
        pass
    cupy.cuda.get_current_stream()  # -> CuPy v10 returns `s1` instead of `s2`.

流现在可以在线程之间共享#

同一个 cupy.cuda.Stream 实例现在可以安全地在多个线程之间共享。

为了实现这一点,CuPy v10 不会销毁流(cudaStreamDestroy),如果该流是任何线程的当前流。

大端数组自动转换为小端#

cupy.array(), cupy.asarray() 及其变体现在总是以小端字节序将数据传输到GPU。

之前,CuPy 会直接将给定的 numpy.ndarray 复制到 GPU 上,而不考虑字节顺序。在 CuPy v10 中,大端序数组在传输前会被转换为小端序,这是 GPU 上的原生字节顺序。这一更改消除了在创建 CuPy 数组之前手动更改数组字节顺序的需要。

Baseline API 更新#

Baseline API 已从 NumPy 1.20 和 SciPy 1.6 升级到 NumPy 1.21 和 SciPy 1.7。CuPy v10 将遵循这些基线版本的上游产品规范。

API 变更#

请注意,已弃用的API可能会在未来的CuPy版本中被移除。

Docker 镜像更新#

CuPy 官方 Docker 镜像(详见 安装)现已更新,使用 CUDA 11.4 和 ROCm 4.3。

CuPy v9#

放弃对 CUDA 9.0 的支持#

CUDA 9.0 不再受支持。请使用 CUDA 9.2 或更高版本。

放弃对 cuDNN v7.5 和 NCCL v2.3 的支持#

cuDNN v7.5(或更早版本)和NCCL v2.3(或更早版本)不再受支持。

放弃对 NumPy 1.16 和 SciPy 1.3 的支持#

不再支持 NumPy 1.16 和 SciPy 1.3。

放弃对 Python 3.5 的支持#

Python 3.5 在 CuPy v9 中不再受支持。

NCCL 和 cuDNN 不再包含在 Wheels 中#

NCCL 和 cuDNN 共享库不再包含在 wheel 中(参见 #4850 的讨论)。如果你没有之前的安装,可以在安装 wheel 后手动安装它们;详情请参阅 安装

cuTENSOR 已启用于 Wheels#

通过wheels安装CuPy时,现在可以使用cuTENSOR。

cupy.cuda.{nccl,cudnn} 模块需要显式导入#

之前,cupy.cuda.ncclcupy.cuda.cudnn 模块是自动导入的。自 CuPy v9 起,这些模块需要显式导入(即,import cupy.cuda.nccl / import cupy.cuda.cudnn。)

Baseline API 更新#

Baseline API 已从 NumPy 1.19 和 SciPy 1.5 升级到 NumPy 1.20 和 SciPy 1.6。CuPy v9 将遵循这些基线版本的 upstream 产品的规范。

自 NumPy 1.20 起,Python 标量类型的别名(cupy.boolcupy.intcupy.floatcupy.complex)已被弃用。在需要时,应使用 cupy.bool_cupy.int_cupy.float_cupy.complex_ 代替。

Docker 镜像更新#

CuPy 官方 Docker 镜像(详见 安装)现已更新,使用 CUDA 11.2 和 Python 3.8。

CuPy v8#

放弃对 CUDA 8.0 和 9.1 的支持#

CUDA 8.0 和 9.1 不再受支持。请使用 CUDA 9.0、9.2、10.0 或更高版本。

放弃对 NumPy 1.15 和 SciPy 1.2 的支持#

不再支持 NumPy 1.15(或更早版本)和 SciPy 1.2(或更早版本)。

Docker 镜像更新#

  • CuPy 官方 Docker 镜像(详见 安装)现已更新,使用 CUDA 10.2 和 Python 3.6。

  • SciPy 和 Optuna 现已预安装。

CUB 支持和编译器要求#

CUB 模块现在默认构建。您可以通过设置 CUPY_ACCELERATORS="cub" 来启用 CUB 的使用(详情请参阅 CUPY_ACCELERATORS)。

由于这一更改,从源代码构建 CuPy 时需要 g++-6 或更高版本。详情请参阅 安装

以下环境变量不再有效:

  • CUB_DISABLED: 使用如前所述的 CUPY_ACCELERATORS

  • CUB_PATH: 不再需要,因为 CuPy 使用 CUDA 自带的 CUB 源(仅在使用 CUDA 11.0 或更高版本时)或 CuPy 发行版中的 CUB。

API 变更#

  • cupy.scatter_add 在 CuPy v4 中已被弃用,现已被移除。请改用 cupyx.scatter_add()

  • cupy.sparse 模块已被弃用,并将在未来的版本中移除。请改用 cupyx.scipy.sparse

  • 已移除 cupy.ndarray.min()cupy.ndarray.max()dtype 参数,以与 NumPy 规范对齐。

  • cupy.allclose() 现在返回结果为 0 维 GPU 数组,而不是 Python 布尔值,以避免设备同步。

  • cupy.RawModule 现在延迟到第一次调用时进行编译,以与 cupy.RawKernel 的行为对齐。

  • cupy.cuda.*_enabled 标志(如 nccl_enablednvtx_enabled 等)已被弃用。请改用 cupy.cuda.*.available 标志(如 cupy.cuda.nccl.availablecupy.cuda.nvtx.available 等)。

  • CHAINER_SEED 环境变量不再有效。请改用 CUPY_SEED

CuPy v7#

放弃对 Python 2.7 和 3.4 的支持#

从 CuPy v7 开始,不再支持 Python 2.7 和 3.4,因为它们分别在 2020 年 1 月(2.7)和 2019 年 3 月(3.4)达到了生命周期结束(EOL)。CuPy v7 支持的最低 Python 版本是 3.5.1。如果您使用的是受影响的 Python 版本,请升级到 安装 下列出的任何更高版本。

CuPy v6#

二进制包忽略 LD_LIBRARY_PATH#

在 CuPy v6 之前,可以使用 LD_LIBRARY_PATH 环境变量来覆盖二进制分发(也称为 wheels)中捆绑的 cuDNN / NCCL 库。在 CuPy v6 中,在发现 cuDNN / NCCL 时将忽略 LD_LIBRARY_PATH;CuPy 二进制分发始终使用随包提供的库,以避免由意外覆盖引起的错误。

CuPy v5#

cupyx.scipy 命名空间#

cupyx.scipy 命名空间已被引入,以提供启用 CUDA 的 SciPy 函数。cupy.sparse 模块已被重命名为 cupyx.scipy.sparsecupy.sparse 将作为向后兼容的别名保留。

放弃对 CUDA 7.0 / 7.5 的支持#

CuPy v5 不再支持 CUDA 7.0 / 7.5。

Docker 镜像更新#

CuPy 官方 Docker 镜像(详见 安装)现已更新,使用 CUDA 9.2 和 cuDNN 7。

要使用这些图像,您可能需要在主机上升级NVIDIA驱动程序。详情请参阅 nvidia-docker 的要求

CuPy v4#

备注

版本号已从 v2 升级到 v4,以与 Chainer 的版本号保持一致。因此,CuPy v3 不存在。

默认内存池#

在 CuPy v4 之前,仅当 CuPy 与 Chainer 一起使用时,内存池才默认启用。在 CuPy v4 中,即使不使用 Chainer,内存池现在也默认启用。内存池通过减轻内存分配和 CPU/GPU 同步的开销,显著提高了性能。

注意

当你监控GPU内存使用情况(例如,使用 nvidia-smi ),你可能会注意到即使数组实例超出作用域后,GPU内存也没有被释放。这是预期行为,因为默认的内存池“缓存”了分配的内存块。

要访问默认的内存池实例,请使用 get_default_memory_pool()get_default_pinned_memory_pool()。您可以访问统计信息并释放内存池中“缓存”的所有未使用的内存块。

import cupy
a = cupy.ndarray(100, dtype=cupy.float32)
mempool = cupy.get_default_memory_pool()

# For performance, the size of actual allocation may become larger than the requested array size.
print(mempool.used_bytes())   # 512
print(mempool.total_bytes())  # 512

# Even if the array goes out of scope, its memory block is kept in the pool.
a = None
print(mempool.used_bytes())   # 0
print(mempool.total_bytes())  # 512

# You can clear the memory block by calling `free_all_blocks`.
mempool.free_all_blocks()
print(mempool.used_bytes())   # 0
print(mempool.total_bytes())  # 0

你甚至可以通过以下代码禁用默认的内存池。请确保在进行任何其他 CuPy 操作之前执行此操作。

import cupy
cupy.cuda.set_allocator(None)
cupy.cuda.set_pinned_memory_allocator(None)

计算能力#

CuPy v4 现在需要计算能力为 3.0 或更高的 NVIDIA GPU。请参阅 CUDA GPU 列表 以检查您的 GPU 是否支持计算能力 3.0。

CUDA 流#

由于 CUDA Stream 在 CuPy v4 中得到了完全支持,用于更改随机数生成器所使用的流的函数 cupy.cuda.RandomState.set_stream 已被移除。请改用 cupy.cuda.Stream.use()

更多详情请参见 #306 中的讨论。

cupyx 命名空间#

cupyx 命名空间已被引入,以提供特定于 CuPy 的功能(即 NumPy 中未提供的功能),同时避免未来的冲突。有关这些函数的列表,请参阅 CuPy 特定功能

对于此规则,cupy.scatter_add() 已被移动到 cupyx.scatter_add()cupy.scatter_add() 仍然可用作别名,但建议使用 cupyx.scatter_add() 代替。

Docker 镜像更新#

CuPy 官方 Docker 镜像(详见 安装)现已更新,以使用 CUDA 8.0 和 cuDNN 6.0。此更改是因为 CUDA 7.5 不支持 NVIDIA Pascal GPU。

要使用这些图像,您可能需要在主机上升级NVIDIA驱动程序。详情请参阅 nvidia-docker 的要求

CuPy v2#

count_nonzero 函数的变更行为#

出于性能考虑,cupy.count_nonzero() 已更改为当 axis=None 时返回零维的 ndarray 而不是 int。更多详情请参见 #154 中的讨论。

兼容性矩阵#

CuPy

CC [1]

CUDA

ROCm

cuTENSOR

NCCL

cuDNN

Python

NumPy

SciPy

基线 API 规范。

文档

v14

3.5~

11.2~

4.3~

2.0~

2.16~

8.8~

3.9~

1.22~

1.7~

NumPy 1.26 和 SciPy 1.11

最新版本

v13

3.5~

11.2~

4.3~

2.0~

2.16~

8.8~

3.9~

1.22~

1.7~

NumPy 1.26 和 SciPy 1.11

稳定版

v12

3.0~9.0

10.2~12.x

4.3 和 5.0

1.4~1.7

2.8~2.17

7.6~8.8

3.8~3.12

1.21~1.26

1.7~1.11

NumPy 1.24 和 SciPy 1.9

v12.3.0

v11

3.0~9.0

10.2~12.0

4.3 和 5.0

1.4~1.6

2.8~2.16

7.6~8.7

3.7~3.11

1.20~1.24

1.6~1.9

NumPy 1.23 和 SciPy 1.8

v11.6.0

v10

3.0~8.x

10.2~11.7

4.0 & 4.2 & 4.3 & 5.0

1.3~1.5

2.8~2.11

7.6~8.4

3.7~3.10

1.18~1.22

1.4~1.8

NumPy 1.21 和 SciPy 1.7

v10.6.0

v9

3.0~8.x

9.2~11.5

3.5~4.3

1.2~1.3

2.4 和 2.6~2.11

7.6~8.2

3.6~3.9

1.17~1.21

1.4~1.7

NumPy 1.20 和 SciPy 1.6

v9.6.0

v8

3.0~8.x

9.0 和 9.2~11.2

3.x [2]

1.2

2.0~2.8

7.0~8.1

3.5~3.9

1.16~1.20

1.3~1.6

NumPy 1.19 和 SciPy 1.5

v8.6.0

v7

3.0~8.x

8.0~11.0

2.x [2]

1.0

1.3~2.7

5.0~8.0

3.5~3.8

1.9~1.19

(未指定)

(未指定)

v7.8.0

v6

3.0~7.x

8.0~10.1

n/a

n/a

1.3~2.4

5.0~7.5

2.7 和 3.4~3.8

1.9~1.17

(未指定)

(未指定)

v6.7.0

v5

3.0~7.x

8.0~10.1

n/a

n/a

1.3~2.4

5.0~7.5

2.7 和 3.4~3.7

1.9~1.16

(未指定)

(未指定)

v5.4.0

v4

3.0~7.x

7.0~9.2

n/a

n/a

1.3~2.2

4.0~7.1

2.7 和 3.4~3.6

1.9~1.14

(未指定)

(未指定)

v4.5.0