NVIDIA DALI 是一个用于解码和增强图像、视频和语音的便携式开源软件库,最近推出了多项功能,可提高性能并支持 DALI 的新用例。这些更新旨在简化 DALI 与现有 PyTorch 数据处理逻辑的集成,通过启用 CPU 到 GPU 流以及添加新的视频解码模式来提高构建数据处理流程的灵活性。这些新功能使 DALI 成为深度学习从业者不可或缺的工具,包括:
- 视频处理改进,通过支持更广泛的选择性解码模式和快速视频容器索引,无需支付不必要的解码开销,从而提高 DALI 的通用性。
- 执行流增强功能,可优化内存消耗。此外,它通过在执行流程中启用 GPU 到 CPU 的传输,为执行模型带来了更大的灵活性。
DALI 代理:高效的 GPU 加速
- 其中一个主要限制是,由于 Python 全局解释器锁定 (GIL) ,使用最新的多核 CPU 架构存在困难。当多核 CPU 架构在消费市场广泛使用时,Python 生态系统引入了全局锁定来简化多线程编程模型,但以降低性能为代价,这会降低处理效率。解决这一问题的最常见方法是在多个独立进程中运行 Python 解释器,使用共享内存或其他 IPC 机制进行通信。虽然这适用于 CPU,但对 GPU 工作编排有一些限制:
- 每个进程都会创建一个单独的 GPU 上下文,在切换不同线程调度的任务时增加了开销。
- 每个进程都会分配自己的 GPU 显存,从而增加整体使用率。
- 在进程之间共享 GPU 显存会增加额外的开销。DALI 通过使用原生多线程来解决这一问题,克服了 Python GIL。
- 在多个 Python 进程之间传输内存时,CPU 和 GPU 之间的数据往返效率可能会降低。这会鼓励在 GPU 运算之后进行 CPU 运算的次优模式,从而增加在 GPU 上来回传输数据的时间,最终降低 GPU 加速的优势。DALI 不鼓励这种模式,确保尽可能减少往返行程,或者根本不会发生。
- 为每个进程创建单独的上下文并分配单独的内存会导致 GPU 工作编排效率低下,从而导致开销和内存占用率过高。

图 1 显示了 Python 中不同的数据处理方法及其局限性。左图展示了最简单的方法,即同时创建多个 Python 线程。但是,由于 Python GIL,一次只能执行一个线程,导致 CPU 未得到充分利用。
中间图使用独立进程而非线程。虽然对 CPU 而言十分高效,但每个进程都会编排 GPU 以独立工作,并且需要昂贵的 IPC 来聚合每个进程的结果。
右图使用带有原生处理功能的 DALI,它可以高效使用所有 CPU 核心并编排 GPU 以正常工作,而不会产生不必要的开销。
DALI 以取代 PyTorch 数据加载程序为代价,有效地解决了这些问题。虽然使用 DALI 从头开始创建新的数据管道非常简单,但重写现有流可能需要大量工作。DALI Proxy 使用户能够有选择地将现有数据管道的一部分卸载到 DALI,非常适合多模态应用,在这种应用中,只有特定的模式 (如视觉处理) 需要加速,而其他部分则使用外部库。此外,它还使 PyTorch 多进程环境中的数据处理 GPU 加速变得方便高效。
该概念基于在主进程中运行的 DALI 服务器实例,该实例还负责编排训练。轻量级 DALI 代理对象将仍在 CPU 上的数据传输到主进程,然后使用原生代码并行处理。这使得 DALI 流水线能够集成到现有的数据加载代码中,仅加速耗时的部分,而不影响逻辑的其余部分,例如复杂的数据读取模式。

使用最简洁方法的 DALI 代理使用示例 (更多示例请参阅 API 文档):
@pipeline_def(num_threads=4, device_id=0)
def rn50_train_pipe():
# the PyTorch data loader passes file names and DALI loads it
filepaths = fn.external_source(name="images", no_copy=True)
jpegs = fn.io.file.read(filepaths)
# decode data on the GPU
images = fn.decoders.image_random_crop(
images, device="mixed", output_type=types.RGB)
# the rest of processing happens on the GPU as well
images = fn.resize(images, resize_x=256, resize_y=256)
images = fn.crop_mirror_normalize(
images,
crop_h=224,
crop_w=224,
mean=[0.485 * 255, 0.456 * 255, 0.406 * 255],
std=[0.229 * 255, 0.224 * 255, 0.225 * 255],
mirror=fn.random.coin_flip())
return images, labels
pipe = rn50_train_pipe(train_dir)
with dali_proxy.DALIServer(pipe) as dali_server:
# we want torchvision.datasets to pass just filenames to DALI
def read_filepath(path):
return np.frombuffer(path.encode(), dtype=np.int8)
# use proxy as the any other transform list
dataset = torchvision.datasets.ImageFolder(
jpeg, transform=dali_server.proxy, loader=read_filepath)
# usual data loader
loader = torch.utils.data.DataLoader(
dataset,
batch_size=batch_size,
num_workers=nworkers,
drop_last=True,
)
for data, target in loader:
# produce_data could be skipped if we use nvidia.dali.plugin.pytorch.experimental.proxy.DataLoader
data = dali_server.produce_data(data)
视频处理改进
DALI 的近期更新对其视频处理能力进行了一系列重大扩展,增加了对可变帧率视频解码的支持,并使用户能够在解码期间直接提取特定帧。这些新功能提高了视频数据工作流的灵活性和可控性。除了这些功能升级之外,视频解码器的初始化时间也得到了优化,使性能与 DALI 之前提供的更专业的解码器保持一致。索引时间的减少对于训练视频基础模型尤其重要,因为这些模型通常需要高效处理数百万个视频样本。
随着深度学习的发展,视频已成为关键数据源。与易于单独加载和处理的图像不同,视频是帧的集合,必须以不同的方式进行处理。每个视频都像是一个迷你数据集,研究人员通常需要使用自定义策略来读取帧。例如,为了提高视频的帧速率,模型可能需要连续的帧。相比之下,对于动作识别,读取每 N 帧有助于减少冗余并避免网络不堪重负。
DALI 支持所有这些用例,能够指定帧数、第一帧、最后一帧、stride (帧之间的步长) 和/ 或显式帧列表。用户可以定义 padding mode,以确保无论视频时长如何,他们始终能收到所请求的确切大小的帧序列。如果视频不包含请求的帧,则复制现有帧。支持的 padding mode 包括 reflect padding、constant padding 和 edge padding。
执行程序增强功能
执行程序增强功能由 exec_dynamic
参数提供,可通过重用内存缓冲区来提高内存管理效率。最初,由于分配成本高昂,DALI 会在不释放内存的情况下主动按需分配内存。最近的进步支持异步按需分配和释放,以便操作有效地重复使用相同的物理内存,同时确保内存不会被覆盖。此更新可提高内存占用率,从而更高效地处理大型数据集。
另一个值得注意的改进是,新的执行模型支持 CPU 到 GPU 到 CPU 的数据传输模式。过去,由于 CPU 和 GPU 之间存在大量数据传输用度,因此不鼓励采用这种模式。然而,NVIDIA GH200 Grace Hopper 超级芯片和 NVIDIA GB200 NVL72 等先进架构的引入及其在 CPU 和 GPU 之间的快速互连开辟了新的可能性,使以前低效的模式得以实现。用户现在可以加速 GPU 上的并行部分,并将数据移回 CPU,以应用本质上属于串行的或 DALI 尚不支持的算法。
总结
最后,NVIDIA DALI 的最新进展显著扩展了其作为深度学习高性能数据预处理库的能力。通过引入 DALI 代理,用户可以获得精细的控制,将 DALI 集成到现有的 PyTorch 工作流中,同时克服 Python 多处理模型施加的限制。增强的视频处理功能使 DALI 更适合现代基于视频的 AI 任务,从而能够灵活高效地处理复杂的帧选择场景。同时,执行程序的改进可以减少内存占用并解锁新的执行模式,特别是在具有快速 CPU-GPU 互连(如 GH200 和 GB200)的系统中。这些更新共同使 DALI 成为跨各种 AI 工作负载扩展数据预处理的通用高效解决方案。
立即试用
要开始使用这些新功能,请探索以下资源:
- 使用增强的video decoder进行视频模型训练,以利用改进的解码功能。
- 测试新的 DALI 执行流程,了解优化的内存管理和灵活的数据传输的优势。
使用 DALI GitHub 页面提问或提出改进建议,了解详情。