如何记录Python代码执行时Intel GPU的操作以排查Hugging Face Transformers的UR运行时错误
Intel Iris Xe这类集成GPU在Hugging Face Transformers上的支持确实还在逐步完善,遇到这种底层UR指令错误确实挺头疼的。结合你已经排除了 dtype 不兼容的情况,我给你分享几个实用的日志/调试方法,帮你定位到底是哪个操作触发了无效参数错误:
一、用Intel IPEX的底层调试日志抓UR调用细节
你用的是Intel GPU专属的PyTorch wheel(也就是IPEX),它基于SYCL/UR框架实现GPU交互,我们可以通过环境变量开启底层调用日志,直接看到出错的UR指令参数:
在终端运行脚本前,先设置这两个环境变量:
export SYCL_PI_TRACE=2 export IPEX_DEBUG=1
然后再执行你的Python脚本。
这两个变量会打印所有和GPU交互的底层Platform Interface(PI)调用,包括每个UR操作的参数、设备信息。你可以重点看报错前最后几个UR调用,就能精准定位是哪个操作的参数不符合Intel GPU的要求——毕竟UR error 45就是「无效参数」,日志里会把参数细节列得清清楚楚。
二、给PyTorch XPU操作打Hook,追踪Python层张量操作
如果想在Python层面精准追踪所有涉及XPU的张量操作,而不是看底层的SYCL日志,可以用PyTorch的TorchDispatchMode写一个简单的日志Hook:
import torch from torch.utils._python_dispatch import TorchDispatchMode class XPULogger(TorchDispatchMode): def __torch_dispatch__(self, func, types, args=(), kwargs=None): kwargs = kwargs or {} # 只记录涉及XPU张量的操作 has_xpu_tensor = any( isinstance(arg, torch.Tensor) and arg.device.type == 'xpu' for arg in args ) or any( isinstance(v, torch.Tensor) and v.device.type == 'xpu' for v in kwargs.values() ) if has_xpu_tensor: print(f"\n[XPU OP] 操作名: {func.__name__}") print(f" 输入张量详情:") for i, arg in enumerate(args): if isinstance(arg, torch.Tensor): print(f" 参数{i}: 设备={arg.device}, dtype={arg.dtype}, 形状={arg.shape}") for k, v in kwargs.items(): if isinstance(v, torch.Tensor): print(f" 关键字参数{k}: 设备={v.device}, dtype={v.dtype}, 形状={v.shape}") # 执行原操作并返回结果 return func(*args, **kwargs) # 在你的模型代码前启用这个日志Hook with XPULogger(): # 这里放你原有代码:加载模型、处理输入、调用generate from transformers import GPT2LMHeadModel, GPT2Tokenizer tokenizer = GPT2Tokenizer.from_pretrained('gpt2') model = GPT2LMHeadModel.from_pretrained('gpt2').to('xpu:0') inputs = tokenizer("Hello, my name is", return_tensors="pt").to('xpu:0') sequences = model.generate(**inputs, max_new_tokens=32)
这个Hook会拦截所有PyTorch操作,只打印涉及XPU张量的内容。你可以重点关注出错的那个to()操作(就是attention_mask.to(device=cache_position.device, dtype=torch.bool)),看看cache_position的设备、形状、dtype是不是有异常——比如会不会cache_position意外跑到CPU上了?或者是一个空张量?
三、临时修改Transformers源码,直接打印关键变量
既然你已经知道出错的代码行在transformers/masking_utils.py的723行,最快的方式就是直接在那行前后加日志,打印相关变量的所有细节:
找到你的Transformers安装路径(你的是/home/cemc/.local/lib/python3.10/site-packages/transformers/),打开masking_utils.py,找到_preprocess_mask_arguments函数里的对应行,修改成:
# 临时添加调试日志 print(f"\n[DEBUG] cache_position 详情:") print(f" 设备: {cache_position.device}, dtype: {cache_position.dtype}, 形状: {cache_position.shape}") print(f" 是否在XPU上: {cache_position.device.type == 'xpu'}") print(f"\n[DEBUG] attention_mask 转换前详情:") print(f" 设备: {attention_mask.device}, dtype: {attention_mask.dtype}, 形状: {attention_mask.shape}") print(f" 是否在XPU上: {attention_mask.device.type == 'xpu'}") try: attention_mask = attention_mask.to(device=cache_position.device, dtype=torch.bool) print(f"\n[DEBUG] attention_mask 转换后详情:") print(f" 设备: {attention_mask.device}, dtype: {attention_mask.dtype}") except Exception as e: print(f"\n[DEBUG] 转换时出错: {e}") # 抛出错误不中断原有流程 raise
运行脚本后,你就能看到这两个张量的所有关键状态,一眼就能发现是不是有隐藏的不兼容问题——比如cache_position其实是CPU张量,导致to()操作要跨设备转换时触发了Intel GPU的参数错误。
四、进阶:用Intel VTune Profiler可视化GPU操作流程
如果需要更全面的硬件级分析,可以用Intel官方的VTune Profiler:
- 安装VTune:Ubuntu上可以通过Intel oneAPI工具包或者apt直接安装
- 创建「GPU Compute」分析任务,选择你的Python脚本作为目标程序
- 运行分析后,VTune会生成一个 timeline 视图,展示所有GPU操作的执行顺序,你可以定位到出错的时间点,查看对应的操作参数和硬件状态
这个工具适合复杂的指令不兼容问题,能帮你看到Python层日志看不到的硬件层面细节。
最后给你两个小建议:
- 确认IPEX、PyTorch、Transformers的版本兼容性——有时候版本不匹配会导致这种底层指令错误,尽量用IPEX官方推荐的对应版本组合
- 可以尝试手动强制把
cache_position移到XPU,比如在出错前加一行cache_position = cache_position.to('xpu:0'),或者先把attention_mask转换成XPU张量再做to()操作,说不定能绕过这个参数错误




