工作原理#

cudf.pandas 被激活时,import pandas(或其任何子模块)会导入一个代理模块,而不是“常规”的 pandas。这个代理模块包含代理类型和代理函数:

In [1]: %load_ext cudf.pandas

In [2]: import pandas as pd

In [3]: pd
Out[3]: <module 'pandas' (ModuleAccelerator(fast=cudf, slow=pandas))>

代理类型/函数的操作尽可能在GPU上执行,否则在CPU上执行,根据需要自动同步。这适用于您代码中的pandas操作以及您可能使用的第三方库中的pandas操作。

cudf-pandas执行流程

所有 cudf.pandas 对象在任何给定时间都是 GPU(cuDF)或 CPU(pandas)对象的代理。属性查找和方法调用首先在 GPU 上尝试(如果需要,从 CPU 复制)。如果失败,则在 CPU 上尝试操作(如果需要,从 GPU 复制)。

此外,cudf.pandas 特别处理了链式方法调用(例如 .groupby().rolling().apply()),这些调用在链的任何级别都可能失败,并且会最小化地回滚和重放链以提供正确的结果。数据仅在必要时自动从主机传输到设备(反之亦然),避免了不必要的设备-主机传输。

当使用 cudf.pandas 时,cuDF 的 pandas 兼容模式 会自动启用,确保与 pandas 特定语义(如默认排序顺序)的一致性。

cudf.pandas 默认使用托管内存池。这使得 cudf.pandas 能够处理比其运行的GPU内存更大的数据集。默认情况下,还启用了托管内存预取功能,以提高内存访问性能。有关CUDA统一内存(托管内存)、性能和预取的更多信息,请参阅这篇NVIDIA开发者博客文章

池分配器提高了分配性能。如果不使用池分配器,内存分配可能会成为瓶颈,具体取决于工作负载。托管内存允许超额订阅GPU内存。这使得cudf.pandas在许多情况下能够处理大于GPU内存的数据,而无需回退到CPU(Pandas)。

注意

在Windows上,特别是Windows子系统Linux(WSL2)上,CUDA托管内存不支持超额订阅,仅支持统一寻址。此外,WSL2上的托管内存具有不理想的性能特征。因此,cudf.pandas在WSL2上使用非托管池分配器,因此cudf.pandas仅限于GPU内存的物理大小。

可以通过更改环境变量 CUDF_PANDAS_RMM_MODE 为以下之一来使用其他内存分配器:

  1. "managed_pool"(默认,如果支持):使用RMM的异步池分配器的CUDA统一内存(托管内存)。

  2. "managed": CUDA 统一内存,(托管内存)没有池分配器。

  3. "async": CUDA的内置池异步池分配器,使用普通的CUDA设备内存。

  4. "pool" (如果 "managed_pool" 不支持则为默认): RMM的异步池分配器,使用普通的CUDA设备内存。

  5. "cuda": 普通的CUDA设备内存,没有池分配器。