XGBoost GPU模式极小内存请求下抛出内存分配错误问题
问题场景
在配置NVIDIA Tesla K80 GPU、CUDA Toolkit 11.3的环境中,通过Python scikit-learn接口运行XGBoost 1.6.1版本,GPU剩余可用内存充足的前提下,运行如下示例代码抛出内存分配错误:
from xgboost import XGBClassifier from sklearn.datasets import load_wine from sklearn.model_selection import train_test_split X, y = load_wine(return_X_y=True, as_frame=True) X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.30, random_state=0) classifier = XGBClassifier(tree_method='gpu_hist') model = classifier.fit(X_train, y_train)
报错核心信息显示GPU空闲内存达11841830912字节,远高于496字节的内存申请量,使用compute-sanitizer工具抓取到核心错误为no kernel image is available for execution on the device。
问题根因
该报错与GPU显存剩余量完全无关,核心原因是GPU计算架构与预编译XGBoost版本不兼容:
- Tesla K80属于Kepler架构GPU,对应CUDA算力版本为sm_37
- 官方PyPI源分发的XGBoost 1.6.1 GPU预编译版本,从1.3.0版本开始就移除了对Kepler架构(sm_30/sm_35/sm_37)的编译支持,内置的CUDA kernel仅包含sm_52及以上算力的二进制镜像,不存在适配K80的可执行kernel代码,因此触发
cudaErrorNoKernelImageForDevice错误。XGBoost的错误捕获逻辑存在缺陷,将该架构不兼容错误误包装为内存分配异常,才会出现仅申请496字节内存、剩余11GB显存仍报错的反常现象。 - 本地安装的CUDA Toolkit 11.3是最后一版支持Kepler架构的CUDA版本,环境本身的CUDA版本不存在问题。
- compute-sanitizer输出的
no kernel image is available for execution on the device是该问题的直接佐证。
解决方案
按操作成本从低到高排序,可选择以下任意一种方案:
- 方案1:降级XGBoost到保留Kepler架构支持的版本
卸载当前版本,安装1.1.0版本的XGBoost,该版本官方预编译包内置sm_37架构适配的kernel,无需额外配置即可直接运行原有代码:pip uninstall -y xgboost pip install xgboost==1.1.0 - 方案2:源码编译适配K80架构的XGBoost 1.6.1
如果必须使用XGBoost 1.6.1的特性,拉取XGBoost v1.6.1版本官方源码编译,编译时指定目标算力为sm_37即可:# 进入源码根目录后创建编译工作目录 mkdir build && cd build # 配置编译参数,开启GPU支持、指定适配K80的算力版本 cmake .. -DUSE_CUDA=ON -DGPU_COMPUTE_VER=37 # 执行编译,-j后数值可替换为当前机器CPU核心数加快编译速度 make -j8 # 安装编译完成的Python包 cd ../python-package pip install . - 方案3:切换为CPU计算模式
如果不需要GPU加速,直接修改树方法参数为CPU支持的取值即可正常运行:classifier = XGBClassifier(tree_method='hist')
内容的提问来源于stack exchange,提问作者Dave Kielpinski
相关产品推荐
相关产品推荐

