You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多GPU运行HuggingFace Dataset.map设with_rank=True时rank参数为None

问题描述

在多GPU环境下对HuggingFace Dataset调用Dataset.map()方法时,参照官方指引编写如下代码:

def translate(example, rank, model):
    os.environ["CUDA_VISIBLE_DEVICES"] = str(rank % torch.cuda.device_count())
    example['premise'] = model.translate(example['premise'])
    return example

ds_map = ds.map(translate, with_rank=True, fn_kwargs= {'model':model})

代码运行时触发如下报错:

TypeError: unsupported operand type(s) for %: 'NoneType' and 'int'

报错指向映射函数translate内接收到的rank参数值为None,需要对应的问题排查指引与可落地方案。

问题原因

with_rank=True仅在Dataset.map()启用多进程并行(即显式传入num_proc参数且值大于1)时,才会向处理函数传入非空的进程rank值。未设置num_proc时,map()默认单进程运行,不会传入rank参数,因此函数接收到的rank为None,触发类型错误。
除此之外原代码还有两个隐性问题:

  1. 在映射函数执行阶段设置CUDA_VISIBLE_DEVICES无效:该环境变量必须在进程启动后、CUDA上下文初始化前设置才会生效,函数执行时CUDA上下文大概率已经完成初始化,修改环境变量无法改变当前进程的可见GPU。
  2. 通过fn_kwargs传入主进程加载的模型存在兼容风险:主进程加载的模型绑定了主进程的CUDA上下文,多进程场景下拷贝到子进程使用时极易触发CUDA设备不匹配、显存泄漏甚至段错误。
排查与修复步骤
  • 首先补全num_proc参数,将值设置为可用GPU的总数量,让rank参数可以正常传入:
import os
import torch
from datasets import load_dataset

# 先统计可用GPU数量
num_gpus = torch.cuda.device_count()

# 错误写法:缺少num_proc,导致rank为None
# ds_map = ds.map(translate, with_rank=True, fn_kwargs= {'model':model})

# 正确基础配置
ds_map = ds.map(
    translate,
    with_rank=True,
    num_proc=num_gpus, # 必须显式指定,开启多进程后with_rank才会生效
    fn_kwargs={"model": model}
)
  • 重构GPU绑定与模型加载逻辑,通过map()的initializer参数在子进程启动阶段完成GPU绑定和模型初始化,从根源规避CUDA上下文冲突问题:
def process_initializer(rank):
    # 子进程启动后第一时间设置可见GPU,此时CUDA尚未初始化,配置可正常生效
    os.environ["CUDA_VISIBLE_DEVICES"] = str(rank)
    global proc_model
    # 每个子进程独立加载模型到当前绑定的GPU,避免跨进程CUDA上下文冲突
    proc_model = load_your_translation_model().to("cuda:0")

def translate(example):
    example["premise"] = proc_model.translate(example["premise"])
    return example

if __name__ == "__main__":
    num_gpus = torch.cuda.device_count()
    ds = load_dataset("your_dataset_name", split="train")
    # 多进程处理逻辑必须放在main作用域下,避免子进程递归启动
    ds_map = ds.map(
        translate,
        num_proc=num_gpus,
        with_rank=True,
        initializer=process_initializer, # 每个子进程启动时先执行初始化函数
    )
  • 兼容项排查:Windows系统默认使用spawn多进程启动模式,对CUDA多进程支持较差,建议优先在Linux环境下运行上述多GPU处理逻辑;如果必须在Windows运行,需要确保所有CUDA相关导入、模型加载逻辑都放在初始化函数或子进程作用域内,不要在主进程提前初始化CUDA上下文。

内容的提问来源于stack exchange,提问作者KoNull

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 16:15:45