本文使用「署名 4.0 国际 (CC BY 4.0)」许可协议,欢迎转载、或重新修改使用,但需要注明来源。 [署名 4.0 国际 (CC BY 4.0)](https://creativecommons.org/licenses/by/4.0/deed.zh) 本文作者: 苏洋 创建时间: 2025年02月08日 统计字数: 33811字 阅读时间: 68分钟阅读 本文链接: https://soulteary.com/2025/02/08/intel-b580-gpu-llm-practice-building-a-better-model-docker-container-environment.html ----- # Intel B580 GPU 大模型容器推理实践:构建更好的模型 Docker 容器环境(二) 本文将详细介绍如何为 Intel ARC 显卡构建更好的模型运行容器环境,来运行 DeepSeek R1 Distill Qwen 1.5 和 7B 模型,并分享完整的实践经验和一些对英特尔显卡、开源生态、模型生态的看法。 ## 写在前面 上一篇文章[《Intel B580 GPU 大模型容器推理实践:以 DeepSeek R1 Distill Qwen 7B 为例(一)》](https://soulteary.com/2025/02/07/intel-b580-gpu-with-docker-and-deepseek-r1-distill-qwen-7b.html)里,我分享了如何在可维护的环境下,使用 Docker 容器来调用显卡,进行模型推理。 在有了上篇文章的基础经验后,接下来我们来聊聊如何让这张显卡和它能够使用到的最新的技术栈的新容器环境进行模型推理。构建一个能充分利用这张显卡最新技术特性,这张卡能够使用到的开源生态最新技术栈的容器运行环境。 ## 构建更好的模型运行环境 想要构建出更好的环境,我们首先要知道现在的容器环境,哪里做的好,哪里又做的不够好。 ### 选择更好的基础,制作更好的容器底包 在上一篇文章中,我们使用的是 Intel IPEX LLM 团队基于 Ubuntu 22.04 构建的容器镜像。 ```Docker FROM intel/oneapi:2024.2.1-0-devel-ubuntu22.04 ``` 镜像的问题在上一篇文章中提到过,就不再展开了,感兴趣的同学自行翻阅。这篇文章我们主要是来解决问题的。 通过查看这个镜像的[构建文件](https://github.com/intel/oneapi-containers/blob/master/images/docker/basekit/Dockerfile.ubuntu-22.04),我们可以发现它主要完成了以下工作:安装基础依赖、GPU 驱动和 Intel oneAPI 相关库。**相对复杂的地方是定义了各种变量,但这些变量是 Intel 相关软件正确运行的基础,尤其是模型相关的软件**。 这些变量通常需要在安装完 Intel oneAPI 后,通过以下命令手动初始化: ```bash . /opt/intel/oneapi/2025.0/oneapi-vars.sh ``` 执行后,系统会显示类似下面的日志,告诉我们各个模块的环境变量配置情况: ```bash :: initializing oneAPI environment ... bash: BASH_VERSION = 5.2.32(1)-release args: Using "$@" for oneapi-vars.sh arguments: :: advisor -- processing etc/advisor/vars.sh :: ccl -- processing etc/ccl/vars.sh :: compiler -- processing etc/compiler/vars.sh :: dal -- processing etc/dal/vars.sh :: debugger -- processing etc/debugger/vars.sh :: dnnl -- processing etc/dnnl/vars.sh :: dpct -- processing etc/dpct/vars.sh :: dpl -- processing etc/dpl/vars.sh :: ipp -- processing etc/ipp/vars.sh :: ippcp -- processing etc/ippcp/vars.sh :: mkl -- processing etc/mkl/vars.sh :: mpi -- processing etc/mpi/vars.sh :: pti -- processing etc/pti/vars.sh :: tbb -- processing etc/tbb/vars.sh :: vtune -- processing etc/vtune/vars.sh :: oneAPI environment initialized :: ``` 为了提升可扩展性,同时又不想太麻烦,我们可以使用基于 Ubuntu 24.04 的 Intel 深度学习[基础镜像 intel/deep-learning-essentials](https://github.com/intel/oneapi-containers/blob/master/images/docker/deep-learning-essentials/Dockerfile.ubuntu-24.04) 来替代 intel/basekit 镜像。 不过要注意,这些镜像的环境变量可能不够完整,使用时可能需要手动补充,就像[去年有用户在 issue 中反馈](https://github.com/intel/oneapi-containers/issues/81)的情况一样。 回到 Intel IPEX LLM 原始镜像文件: ```bash FROM intel/oneapi:2024.2.1-0-devel-ubuntu22.04 ARG http_proxy ARG https_proxy ENV TZ=Asia/Shanghai ENV PYTHONUNBUFFERED=1 # When cache is enabled SYCL runtime will try to cache and reuse JIT-compiled binaries. ENV SYCL_CACHE_PERSISTENT=1 COPY chat.py /llm/chat.py COPY benchmark.sh /llm/benchmark.sh # Disable pip's cache behavior ARG PIP_NO_CACHE_DIR=false ``` 上面的文件中,除了引用了 Ubuntu 22.04 的 Intel basekit 镜像之外,做了一些基础的变量声明之外,主要引入了 LLM 测试文件和 POC 使用的 Python 聊天程序示例。 有趣的是,维护 Intel IPEX LLM 镜像的国人 Intel 工程师,或许平时在本地构建和调试镜像不方便,经常遇到网络问题,在镜像的一开头就声明了两个变量,用于设置网络代理。(英特尔是否该帮助你自己的开发者先解决下开发效率问题呢) 当然,原作者可能对容器特性了解不够深入,没有充分利用容器构建缓存的优势,除了将可能高频变动的内容就放置在容器定义开始,还刻板的将所有安装命令合并成了一个Docker指令。 在老版本容器构建中,每增加一条容器指令,容器大小会增加几MB。但对于我们的模型推理镜像来说,最终文件通常都在 10~20GB 左右,为了节省这几十MB(假设有几十个Docker指令)而牺牲构建效率是得不偿失的。 接下来,我们就对原始镜像做一些优化调整:**不仅优化程序执行环境,也优化我们开发定制镜像、调试环境的效率。** Python 是这个环境的基础依赖,所以我们可以把 Python 的安装工具放在容器最开始的位置。同时,我们可以将系统软件源和 Python 软件源替换为国内镜像,加快软件包下载速度。 在初始化 Python 环境时,原始镜像使用的是三方软件源方案: ```Docker add-apt-repository ppa:deadsnakes/ppa -y && \ apt-get install -y --no-install-recommends python3.11 git curl wget ``` 新的镜像中,我们选择使用 miniconda 进行替代,方便后续随时切换不同的版本。整个镜像的基础定义如下: ```Docker FROM intel/deep-learning-essentials:2025.0.2-0-devel-ubuntu24.04 LABEL maintainer="soulteary " LABEL description="Dockerfile for Intel GPU based deep learning development environment." ARG USE_CHINA_MIRROR=false ENV USE_CHINA_MIRROR=$USE_CHINA_MIRROR # Set up the mirror for Ubuntu RUN if [ "$USE_CHINA_MIRROR" = "true" ]; then \ sed -i 's/\(archive\|security\).ubuntu.com/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/sources.list.d/ubuntu.sources; \ fi # Install the necessary packages RUN apt-get update && apt upgrade -y && \ apt-get install -y --no-install-recommends clinfo && \ rm -rf /var/lib/apt/lists/* # Install the necessary Python installer # https://soulteary.com/2022/12/09/use-docker-to-quickly-get-started-with-the-chinese-stable-diffusion-model-taiyi.html ENV PATH="/root/miniconda3/bin:${PATH}" ENV CONDA_URL=https://repo.anaconda.com/miniconda/ ENV CONDA_MIRROR=https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/ RUN if [ "$USE_CHINA_MIRROR" = "true" ]; then export CONDA_URL=$CONDA_MIRROR; fi; \ curl -LO $CONDA_URL/Miniconda3-latest-Linux-x86_64.sh && \ mkdir /root/.conda && \ bash Miniconda3-latest-Linux-x86_64.sh -b && \ rm -f Miniconda3-latest-Linux-x86_64.sh # https://soulteary.com/2025/01/17/guide-to-setting-up-ubuntu-24-04-basic-development-environment.html RUN if [ "$USE_CHINA_MIRROR" = "true" ]; then \ conda config --set show_channel_urls true && \ conda config --remove-key channels && \ conda config --add channels defaults && \ conda config --add default_channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/msys2 && \ conda config --add default_channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/r && \ conda config --add default_channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main && \ ( echo "custom_channels:" >> ~/.condarc ) && \ ( echo " conda-forge: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud" >> ~/.condarc ) && \ ( echo " pytorch: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud" >> ~/.condarc ); \ fi ``` 在基础镜像中,我们定义了一个构建变量 `USE_CHINA_MIRROR`。当我们启用这个变量时,构建容器过程将使用国内的软件源进行加速。 ### 清理会影响正常安装的陈旧软件包 在更新 Intel Compute Runtime (计算运行时)之前,我们需要先移除一些过时的软件包。这些包如果不删除,可能会和新版本产生冲突,影响后续安装: ```Docker # Remove breaks install packages RUN apt-get remove -y libze-dev libze-intel-gpu1 ``` 这个问题其实由来已久,[在 ARC 770 时期就有社区用户提出过](https://github.com/intel/compute-runtime/issues/770)。 ### 升级 Intel Compute Runtime 和显卡驱动程序 现在,我们可以安装最新版本的运行时软件包了。Intel 的 Compute Runtime 和我们熟悉的 Nvidia CUDA 有几分相似,但设计重点有所不同,虽然都是专注于高性能并行计算的工具。但相比较 Nvidia 只专注 GPU 外,Intel 的计算运行时的野心更大,除了支持 Intel GPU 之外,还支持 CPU、FPGA、CPU 等。 这些包来自 [Intel Compute Runtime 团队](https://github.com/intel/compute-runtime/releases/tag/24.52.32224.5)的最新发布(从 24.39.31294.12 升级到了 24.52.32224.5): ```Docker # Intel GPU OpenCL Driver and Intel GPU Compute Runtime # https://github.com/intel/compute-runtime/releases/tag/24.52.32224.5 WORKDIR /tmp/neo RUN curl -LO https://github.com/intel/intel-graphics-compiler/releases/download/v2.5.6/intel-igc-core-2_2.5.6+18417_amd64.deb && \ curl -LO https://github.com/intel/intel-graphics-compiler/releases/download/v2.5.6/intel-igc-opencl-2_2.5.6+18417_amd64.deb && \ curl -LO https://github.com/intel/compute-runtime/releases/download/24.52.32224.5/intel-level-zero-gpu-dbgsym_1.6.32224.5_amd64.ddeb && \ curl -LO https://github.com/intel/compute-runtime/releases/download/24.52.32224.5/intel-level-zero-gpu_1.6.32224.5_amd64.deb && \ curl -LO https://github.com/intel/compute-runtime/releases/download/24.52.32224.5/intel-opencl-icd-dbgsym_24.52.32224.5_amd64.ddeb && \ curl -LO https://github.com/intel/compute-runtime/releases/download/24.52.32224.5/intel-opencl-icd_24.52.32224.5_amd64.deb && \ curl -LO https://github.com/intel/compute-runtime/releases/download/24.52.32224.5/libigdgmm12_22.5.5_amd64.deb && \ curl -LO https://github.com/intel/compute-runtime/releases/download/24.52.32224.5/ww52.sum && \ sha256sum -c ww52.sum && \ dpkg -i *.deb && \ rm -rf * ``` 除了使用更新版本的软件包之外,安装过程中,程序还对这些软件包补充进行了签名校验。值得一提的是,这个团队的代码质量在 Intel 众多项目中算是相当不错的。这可能和团队规模有关,光是核心贡献者就有二十多位。 接下来,我们还需要从 Intel oneAPI Level Zero 项目中获取包含最新bug修复的版本: ```Docker # oneAPI Level Zero Loader # https://github.com/oneapi-src/level-zero/releases/tag/v1.20.2 WORKDIR /tmp/level-zero RUN curl -LO https://github.com/oneapi-src/level-zero/releases/download/v1.20.2/level-zero_1.20.2+u24.04_amd64.deb && \ curl -LO https://github.com/oneapi-src/level-zero/releases/download/v1.20.2/level-zero-devel_1.20.2+u24.04_amd64.deb && \ dpkg -i *.deb && \ rm -rf *.deb ``` Intel Level Zero 提供了低级 API,允许开发者对 Intel 硬件进行直接的访问和控制,能够细粒度的进行管理。而 Level Zero Loader 则是其中比较关键的组件之一,它能够控制 Level Zero 不同硬件的驱动和模型的加载,因为我们使用的是新硬件,所以也需要更新它。 ### 配置 Intel PyTorch 环境 前面我们已经完成了 Python 包管理工具的安装,现在让我们用它来搭建 Intel PyTorch 的运行环境: ```Docker # Intel GPU PyTorch Environment RUN conda install python=3.11 -y ENV PIP_ROOT_USER_ACTION=ignore ENV PYTHONUNBUFFERED=1 ENV PIP_NO_CACHE_DIR=true ENV IPEX_LLM_URL=https://pytorch-extension.intel.com/release-whl/stable/xpu/us/ ENV IPEX_LLM_MIRROR=https://pytorch-extension.intel.com/release-whl/stable/xpu/cn/ ENV PYTORCH_TRITON_XPU_URL=https://download.pytorch.org/whl/nightly/xpu ENV PYTORCH_TRITON_XPU_MIRROR=https://mirror.sjtu.edu.cn/pytorch-wheels/nightly/xpu RUN if [ "$USE_CHINA_MIRROR" = "true" ]; then export IPEX_LLM_URL=$IPEX_LLM_MIRROR; fi; \ if [ "$PYTORCH_TRITON_XPU_URL" = "true" ]; then export PYTORCH_TRITON_XPU_URL=$PYTORCH_TRITON_XPU_MIRROR; fi; \ pip install --pre --upgrade ipex-llm[xpu_arc]==2.2.0b20250205 --extra-index-url $IPEX_LLM_URL && \ pip install --pre pytorch-triton-xpu==3.2.0+gite98b6fcb --index-url $PYTORCH_TRITON_XPU_URL && \ rm -Rf /root/.cache/pip ``` 这里我把 [Intel PyTorch Triton](https://github.com/intel/intel-xpu-backend-for-triton) 版本升级到了 3.2.0。新版本修复了不少问题,如果你打算使用 2025.x 版本的 oneAPI,至少需要升级到 v3.2.0b1。 ### 解决 `GLIBCXX_3.4.29 not found` 报错 当我们使用 IPEX LLM 团队提供的 PyTorch 包时,如果和 conda 一起使用可能会遇到这样的错误: ```bash libstdc++.so.6: version `GLIBCXX_3.4.29' not found ``` 好在解决方案很简单,我们可以参考 [pybind11 社区的解决方案](https://github.com/pybind/pybind11/discussions/3453): ```Docker # Fix conda libc++ errors RUN rm /root/miniconda3/lib/libstdc++.so.6 && \ rm /root/miniconda3/lib/libstdc++.so.6.0.29 && \ rm /root/miniconda3/lib/libstdc++.so && \ ln -s /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.33 /root/miniconda3/lib/libstdc++.so.6 && \ ln -s /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.33 /root/miniconda3/lib/libstdc++.so.6.0.29 && \ ln -s /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.33 /root/miniconda3/lib/libstdc++.so ``` ### 补充 IPEX LLM 基础依赖问题 IPEX 团队提供的镜像中漏掉了一些基础依赖。虽然不会直接导致程序崩溃,但运行时会有警告提示。而且如果你要用多模态模型,这些缺失的依赖可能会导致部分功能不可用: ```Docker # Fix Intel IPEX LLM errors and warnings RUN apt-get update && apt-get install -y --no-install-recommends libpng16-16 libjpeg-turbo8 libaio-dev && \ rm -rf /var/lib/apt/lists/* && \ pip install -U transformers && \ pip install 'accelerate>=0.26.0' ``` 在上面的修正里,我们安装了包含更新的加速推理方案的 `accelerate` 以及对模型支持推理兼容性更好的新版本的 `transformers`。当然,目前 IPEX 团队的镜像是无法正常使用最新版本的 `transformers`,这个问题我们稍后在推理阶段修复,因为这个事情和你的 AI 应用程序代码相关。 ## 进行新容器的推理验证 开始推理验证之前,先来进行必要的镜像构建工作。 ### 构建并使用新的容器镜像 完整的容器镜像代码,我开源在了 [soulteary/better-intel-ai-docker-image](https://github.com/soulteary/better-intel-ai-docker-image): ```Docker FROM intel/deep-learning-essentials:2025.0.2-0-devel-ubuntu24.04 LABEL maintainer="soulteary " LABEL description="Dockerfile for Intel GPU based deep learning development environment." ARG USE_CHINA_MIRROR=false ENV USE_CHINA_MIRROR=$USE_CHINA_MIRROR # Set up the mirror for Ubuntu RUN if [ "$USE_CHINA_MIRROR" = "true" ]; then \ sed -i 's/\(archive\|security\).ubuntu.com/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/sources.list.d/ubuntu.sources; \ fi # Install the necessary packages RUN apt-get update && apt upgrade -y && \ apt-get install -y --no-install-recommends clinfo && \ rm -rf /var/lib/apt/lists/* # Install the necessary Python installer # https://soulteary.com/2022/12/09/use-docker-to-quickly-get-started-with-the-chinese-stable-diffusion-model-taiyi.html ENV PATH="/root/miniconda3/bin:${PATH}" ENV CONDA_URL=https://repo.anaconda.com/miniconda/ ENV CONDA_MIRROR=https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/ RUN if [ "$USE_CHINA_MIRROR" = "true" ]; then export CONDA_URL=$CONDA_MIRROR; fi; \ curl -LO $CONDA_URL/Miniconda3-latest-Linux-x86_64.sh && \ mkdir /root/.conda && \ bash Miniconda3-latest-Linux-x86_64.sh -b && \ rm -f Miniconda3-latest-Linux-x86_64.sh # https://soulteary.com/2025/01/17/guide-to-setting-up-ubuntu-24-04-basic-development-environment.html RUN if [ "$USE_CHINA_MIRROR" = "true" ]; then \ conda config --set show_channel_urls true && \ conda config --remove-key channels && \ conda config --add channels defaults && \ conda config --add default_channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/msys2 && \ conda config --add default_channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/r && \ conda config --add default_channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main && \ ( echo "custom_channels:" >> ~/.condarc ) && \ ( echo " conda-forge: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud" >> ~/.condarc ) && \ ( echo " pytorch: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud" >> ~/.condarc ); \ fi # Remove breaks install packages RUN apt-get remove -y libze-dev libze-intel-gpu1 # Intel GPU OpenCL Driver and Intel GPU Compute Runtime # https://github.com/intel/compute-runtime/releases/tag/24.52.32224.5 WORKDIR /tmp/neo RUN curl -LO https://github.com/intel/intel-graphics-compiler/releases/download/v2.5.6/intel-igc-core-2_2.5.6+18417_amd64.deb && \ curl -LO https://github.com/intel/intel-graphics-compiler/releases/download/v2.5.6/intel-igc-opencl-2_2.5.6+18417_amd64.deb && \ curl -LO https://github.com/intel/compute-runtime/releases/download/24.52.32224.5/intel-level-zero-gpu-dbgsym_1.6.32224.5_amd64.ddeb && \ curl -LO https://github.com/intel/compute-runtime/releases/download/24.52.32224.5/intel-level-zero-gpu_1.6.32224.5_amd64.deb && \ curl -LO https://github.com/intel/compute-runtime/releases/download/24.52.32224.5/intel-opencl-icd-dbgsym_24.52.32224.5_amd64.ddeb && \ curl -LO https://github.com/intel/compute-runtime/releases/download/24.52.32224.5/intel-opencl-icd_24.52.32224.5_amd64.deb && \ curl -LO https://github.com/intel/compute-runtime/releases/download/24.52.32224.5/libigdgmm12_22.5.5_amd64.deb && \ curl -LO https://github.com/intel/compute-runtime/releases/download/24.52.32224.5/ww52.sum && \ sha256sum -c ww52.sum && \ dpkg -i *.deb && \ rm -rf * # oneAPI Level Zero Loader # https://github.com/oneapi-src/level-zero/releases/tag/v1.20.2 WORKDIR /tmp/level-zero RUN curl -LO https://github.com/oneapi-src/level-zero/releases/download/v1.20.2/level-zero_1.20.2+u24.04_amd64.deb && \ curl -LO https://github.com/oneapi-src/level-zero/releases/download/v1.20.2/level-zero-devel_1.20.2+u24.04_amd64.deb && \ dpkg -i *.deb && \ rm -rf *.deb # Intel GPU PyTorch Environment RUN conda install python=3.11 -y ENV PIP_ROOT_USER_ACTION=ignore ENV PYTHONUNBUFFERED=1 ENV PIP_NO_CACHE_DIR=true ENV IPEX_LLM_URL=https://pytorch-extension.intel.com/release-whl/stable/xpu/us/ ENV IPEX_LLM_MIRROR=https://pytorch-extension.intel.com/release-whl/stable/xpu/cn/ ENV PYTORCH_TRITON_XPU_URL=https://download.pytorch.org/whl/nightly/xpu ENV PYTORCH_TRITON_XPU_MIRROR=https://mirror.sjtu.edu.cn/pytorch-wheels/nightly/xpu RUN if [ "$USE_CHINA_MIRROR" = "true" ]; then export IPEX_LLM_URL=$IPEX_LLM_MIRROR; fi; \ if [ "$PYTORCH_TRITON_XPU_URL" = "true" ]; then export PYTORCH_TRITON_XPU_URL=$PYTORCH_TRITON_XPU_MIRROR; fi; \ pip install --pre --upgrade ipex-llm[xpu_arc]==2.2.0b20250205 --extra-index-url $IPEX_LLM_URL && \ pip install --pre pytorch-triton-xpu==3.2.0+gite98b6fcb --index-url $PYTORCH_TRITON_XPU_URL && \ rm -Rf /root/.cache/pip # Fix conda libc++ errors RUN rm /root/miniconda3/lib/libstdc++.so.6 && \ rm /root/miniconda3/lib/libstdc++.so.6.0.29 && \ rm /root/miniconda3/lib/libstdc++.so && \ ln -s /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.33 /root/miniconda3/lib/libstdc++.so.6 && \ ln -s /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.33 /root/miniconda3/lib/libstdc++.so.6.0.29 && \ ln -s /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.33 /root/miniconda3/lib/libstdc++.so # Fix Intel IPEX LLM errors and warnings RUN apt-get update && apt-get install -y --no-install-recommends libpng16-16 libjpeg-turbo8 libaio-dev && \ rm -rf /var/lib/apt/lists/* && \ pip install -U transformers && \ pip install 'accelerate>=0.26.0' WORKDIR /llm ``` 构建镜像很简单,从项目中下载 `Dockerfile` 文件,或者将上面的内容保存为 `Dockerfile` 后执行: ```bash docker build --build-arg=USE_CHINA_MIRROR=true -t soulteary/better-intel-env:2025.02.08 . ``` 耐心等待软件都下载好,镜像就自动构建好了: ```bash => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 5.53kB 0.0s => [internal] load metadata for docker.io/intel/deep-learning-essentials:2025.0.2-0-devel-ubuntu24.04 0.0s => [internal] load .dockerignore 0.0s => => transferring context: 2B 0.0s => [ 1/14] FROM docker.io/intel/deep-learning-essentials:2025.0.2-0-devel-ubuntu24.04 0.0s => CACHED [ 2/14] RUN if [ "true" = "true" ]; then sed -i 's/\(archive\|security\).ubuntu.com/mirrors.tuna.tsinghua. 0.0s => CACHED [ 3/14] RUN apt-get update && apt upgrade -y && apt-get install -y --no-install-recommends clinfo && rm -r 0.0s => CACHED [ 4/14] RUN if [ "true" = "true" ]; then export CONDA_URL=https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/ 0.0s => CACHED [ 5/14] RUN if [ "true" = "true" ]; then conda config --set show_channel_urls true && conda config 0.0s => CACHED [ 6/14] RUN apt-get remove -y libze-dev libze-intel-gpu1 0.0s => CACHED [ 7/14] WORKDIR /tmp/neo 0.0s => CACHED [ 8/14] RUN curl -LO https://github.com/intel/intel-graphics-compiler/releases/download/v2.5.6/intel-igc-core-2_2. 0.0s => CACHED [ 9/14] WORKDIR /tmp/level-zero 0.0s => CACHED [10/14] RUN curl -LO https://github.com/oneapi-src/level-zero/releases/download/v1.20.2/level-zero_1.20.2+u24.04_a 0.0s => CACHED [11/14] RUN conda install python=3.11 -y 0.0s => CACHED [12/14] RUN if [ "true" = "true" ]; then export IPEX_LLM_URL=https://pytorch-extension.intel.com/release-whl/stabl 0.0s => CACHED [13/14] RUN rm /root/miniconda3/lib/libstdc++.so.6 && rm /root/miniconda3/lib/libstdc++.so.6.0.29 && rm /r 0.0s => CACHED [14/14] RUN apt-get update && apt-get install -y --no-install-recommends libpng16-16 libjpeg-turbo8 libaio-dev && 0.0s => exporting to image 0.0s => => exporting layers 0.0s => => writing image sha256:00cf6fc449074a8100634bff96158f979a356773545a450674454bc51c36a36a 0.0s => => naming to docker.io/soulteary/better-intel-env:2025.02.08 ``` 接着和之前一样,执行命令进入容器环境: ```bash docker run --rm -it --privileged --net=host --device=/dev/dri --memory="16G" --shm-size="16g" -v `pwd`/intel-llm:/llm/models soulteary/better-intel-env:2025.02.08 ``` 命令执行完毕,我们就进入了交互式终端环境。在新的环境中,我们先执行下面的命令重置容器内的变量: ```bash # . /opt/intel/oneapi/2025.0/oneapi-vars.sh --force :: initializing oneAPI environment ... bash: BASH_VERSION = 5.2.21(1)-release args: Using "$@" for oneapi-vars.sh arguments: --force :: ccl -- processing etc/ccl/vars.sh :: compiler -- processing etc/compiler/vars.sh :: debugger -- processing etc/debugger/vars.sh :: dnnl -- processing etc/dnnl/vars.sh :: dpl -- processing etc/dpl/vars.sh :: mkl -- processing etc/mkl/vars.sh :: mpi -- processing etc/mpi/vars.sh :: pti -- processing etc/pti/vars.sh :: tbb -- processing etc/tbb/vars.sh :: oneAPI environment initialized :: ``` 接下来,编写模型推理应用程序。 ### 编写模型推理脚本 因为 DeepSeek R1 Distill Qwen 是基于千问的,这次我们就以 Qwen 团队的示例程序(Qwen 2.5项目示例 [examples/demo/cli\_demo.py](https://github.com/QwenLM/Qwen2.5/blob/main/examples/demo/cli_demo.py))为基础来改造一个推理程序。 之前已经测试过 API 方式,这次我们来试试 CLI 终端方式使用模型。我们将示例中的 `AutoModelForCausalLM` 替换为 IPEX 团队的修改版,并调整 `_load_model_tokenizer` 函数中的模型加载方法,将系统加载后到模型内容,转换为 `xpu` 类型即可。 完整代码如下: ```python # Copyright (c) Alibaba Cloud. # # This source code is licensed under the license found in the # LICENSE file in the root directory of this source tree. """A simple command-line interactive chat demo.""" import argparse import os import platform import shutil from copy import deepcopy from threading import Thread import torch from transformers import AutoTokenizer, TextIteratorStreamer from transformers.trainer_utils import set_seed from ipex_llm.transformers import AutoModelForCausalLM DEFAULT_CKPT_PATH = "./models/deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B/" _WELCOME_MSG = """\ Welcome to use Qwen2.5-Instruct model, type text to start chat, type :h to show command help. (欢迎使用 Qwen2.5-Instruct 模型,输入内容即可进行对话,:h 显示命令帮助。) Note: This demo is governed by the original license of Qwen2.5. We strongly advise users not to knowingly generate or allow others to knowingly generate harmful content, including hate speech, violence, pornography, deception, etc. (注:本演示受Qwen2.5的许可协议限制。我们强烈建议,用户不应传播及不应允许他人传播以下内容,包括但不限于仇恨言论、暴力、色情、欺诈相关的有害信息。) """ _HELP_MSG = """\ Commands: :help / :h Show this help message 显示帮助信息 :exit / :quit / :q Exit the demo 退出Demo :clear / :cl Clear screen 清屏 :clear-history / :clh Clear history 清除对话历史 :history / :his Show history 显示对话历史 :seed Show current random seed 显示当前随机种子 :seed Set random seed to 设置随机种子 :conf Show current generation config 显示生成配置 :conf = Change generation config 修改生成配置 :reset-conf Reset generation config 重置生成配置 """ _ALL_COMMAND_NAMES = [ "help", "h", "exit", "quit", "q", "clear", "cl", "clear-history", "clh", "history", "his", "seed", "conf", "reset-conf", ] def _setup_readline(): try: import readline except ImportError: return _matches = [] def _completer(text, state): nonlocal _matches if state == 0: _matches = [ cmd_name for cmd_name in _ALL_COMMAND_NAMES if cmd_name.startswith(text) ] if 0 <= state < len(_matches): return _matches[state] return None readline.set_completer(_completer) readline.parse_and_bind("tab: complete") def _load_model_tokenizer(args): tokenizer = AutoTokenizer.from_pretrained( args.checkpoint_path, resume_download=True, ) model = AutoModelForCausalLM.from_pretrained( args.checkpoint_path, torch_dtype="auto", device_map="auto", resume_download=True, ).eval().to('xpu') model.generation_config.max_new_tokens = 2048 # For chat. return model, tokenizer def _gc(): import gc gc.collect() if torch.cuda.is_available(): torch.cuda.empty_cache() def _clear_screen(): if platform.system() == "Windows": os.system("cls") else: os.system("clear") def _print_history(history): terminal_width = shutil.get_terminal_size()[0] print(f"History ({len(history)})".center(terminal_width, "=")) for index, (query, response) in enumerate(history): print(f"User[{index}]: {query}") print(f"Qwen[{index}]: {response}") print("=" * terminal_width) def _get_input() -> str: while True: try: message = input("User> ").strip() except UnicodeDecodeError: print("[ERROR] Encoding error in input") continue except KeyboardInterrupt: exit(1) if message: return message print("[ERROR] Query is empty") def _chat_stream(model, tokenizer, query, history): conversation = [] for query_h, response_h in history: conversation.append({"role": "user", "content": query_h}) conversation.append({"role": "assistant", "content": response_h}) conversation.append({"role": "user", "content": query}) input_text = tokenizer.apply_chat_template( conversation, add_generation_prompt=True, tokenize=False, ) inputs = tokenizer([input_text], return_tensors="pt").to(model.device) streamer = TextIteratorStreamer( tokenizer=tokenizer, skip_prompt=True, timeout=60.0, skip_special_tokens=True ) generation_kwargs = { **inputs, "streamer": streamer, } thread = Thread(target=model.generate, kwargs=generation_kwargs) thread.start() for new_text in streamer: yield new_text def main(): parser = argparse.ArgumentParser( description="Qwen2.5-Instruct command-line interactive chat demo." ) parser.add_argument( "-c", "--checkpoint-path", type=str, default=DEFAULT_CKPT_PATH, help="Checkpoint name or path, default to %(default)r", ) parser.add_argument("-s", "--seed", type=int, default=1234, help="Random seed") parser.add_argument( "--cpu-only", action="store_true", help="Run demo with CPU only" ) args = parser.parse_args() history, response = [], "" model, tokenizer = _load_model_tokenizer(args) orig_gen_config = deepcopy(model.generation_config) _setup_readline() _clear_screen() print(_WELCOME_MSG) seed = args.seed while True: query = _get_input() # Process commands. if query.startswith(":"): command_words = query[1:].strip().split() if not command_words: command = "" else: command = command_words[0] if command in ["exit", "quit", "q"]: break elif command in ["clear", "cl"]: _clear_screen() print(_WELCOME_MSG) _gc() continue elif command in ["clear-history", "clh"]: print(f"[INFO] All {len(history)} history cleared") history.clear() _gc() continue elif command in ["help", "h"]: print(_HELP_MSG) continue elif command in ["history", "his"]: _print_history(history) continue elif command in ["seed"]: if len(command_words) == 1: print(f"[INFO] Current random seed: {seed}") continue else: new_seed_s = command_words[1] try: new_seed = int(new_seed_s) except ValueError: print( f"[WARNING] Fail to change random seed: {new_seed_s!r} is not a valid number" ) else: print(f"[INFO] Random seed changed to {new_seed}") seed = new_seed continue elif command in ["conf"]: if len(command_words) == 1: print(model.generation_config) else: for key_value_pairs_str in command_words[1:]: eq_idx = key_value_pairs_str.find("=") if eq_idx == -1: print("[WARNING] format: =") continue conf_key, conf_value_str = ( key_value_pairs_str[:eq_idx], key_value_pairs_str[eq_idx + 1 :], ) try: conf_value = eval(conf_value_str) except Exception as e: print(e) continue else: print( f"[INFO] Change config: model.generation_config.{conf_key} = {conf_value}" ) setattr(model.generation_config, conf_key, conf_value) continue elif command in ["reset-conf"]: print("[INFO] Reset generation config") model.generation_config = deepcopy(orig_gen_config) print(model.generation_config) continue else: # As normal query. pass # Run chat. set_seed(seed) _clear_screen() print(f"\nUser: {query}") print(f"\nQwen: ", end="") try: partial_text = "" for new_text in _chat_stream(model, tokenizer, query, history): print(new_text, end="", flush=True) partial_text += new_text response = partial_text print() except KeyboardInterrupt: print("[WARNING] Generation interrupted") continue history.append((query, response)) if __name__ == "__main__": main() ``` 将代码先保存为 `app.py`,距离启动测试,我们还差最后一步,修正一些 IPEX 软件环境和 `transformers` 的兼容性问题。 ### 修正上下游软件包问题 虽然 IPEX 团队对 HuggingFace transformers 的不同版本做了一些基础适配: ```python trans_version = transformers.__version__ if version.parse(trans_version) >= version.parse("4.39.0"): try: from trl.core import top_k_top_p_filtering except ModuleNotFoundError: log4Error.invalidInputError(False, "For transformers version >= 4.39.0, pip install trl") else: from transformers import top_k_top_p_filtering ``` 但 transformers 这个库发展太快,在去年年底进行了[一次重大重构](https://github.com/huggingface/transformers/commit/2c47618c1a282f925446506d53108dc6e82d9ef0#diff-06392bad3b9e97be9ade60d4ac46f73b6809388f4d507c2ba1384ab872711c51)。这次重构导致很多软件包出现了奇怪的报错,很多甚至是静默错误(报不出来错、报错位置不正确)。 此外,IPEX 等框架依赖的 transformers 中的 `top_k_top_p_filtering` 函数,在之前重构后被迁移到了 huggingface/trl 工具中,但在今年[年底重构时又被删除](https://github.com/huggingface/trl/commit/8c49ea39ec2e11ce4c61291ff2ad59edb46522aa)。这导致社区中许多其他软件也无法正常工作。 如果我们想用较新版本的 HF Transformers 框架来推理,需要锁定软件版本到合适的版本号。下面是 IPEX PyTorch 环境能用的最新版本: ```bash pip install transformers==4.47.1 pip install git+https://github.com/huggingface/trl@d6a8f2c ``` 另外,为了修复新的流式输出问题,还需要安装: ```bash pip install openai python-multipart ``` ### 测试模型 ![新容器环境下的测试](https://attachment.soulteary.com/2025/02/08/b580-r1-test.jpg) 完成上述工作后,执行 `python app.py` 就可以使用相对最新的软件基础来运行模型啦。本文主要的目标是改进 Intel GPU 容器的运行环境,所以,模型这里我就进行了简单的三轮对话(你可以自行完善应用和调整推理模型参数量,折腾更有意思的东西)。 下面是模型的第二轮问题和输出: ```bash User: 玩好打野的技巧 Qwen: 嗯,我现在要学习如何玩好打野的技巧。首先,我需要了解什么是打野。打野在游戏中的角色通常是负责控制比赛节奏、消耗资源、保护队友以及创造反手的机会的角色。在游戏的各个版本中,打野的角色可能会有所变化,但基本的技能和策略应该是一样的。 首先,我应该了解一下游戏的基本规则。游戏中的打野通常需要控制节奏,所以在比赛中需要快速移动和消耗资源。资源消耗主要是通过技能的使用,比如技能点、经济消耗、技能消耗等等。我需要了解每个技能的使用时机和效果,以便在比赛中合理使用技能。 然后,我想到了资源消耗和消耗机制。资源消耗通常分为技能消耗和经济消耗。技能消耗是指使用技能时会消耗一定数量的资源,而经济消耗则是指玩家的经济水平决定了能否使用技能。我需要了解如何合理安排技能的使用时间,避免资源耗尽,同时又不影响游戏节奏。 接下来,我应该学习一些打野常用的技能。常见的打野技能包括控制技能、消耗技能、技能消耗、技能消耗等等。控制技能通常用于控制比赛节奏,消耗技能用于消耗资源,技能消耗用于消耗经济资源,技能消耗用于消耗资源。每个技能都有不同的使用时机,需要根据比赛情况来选择。 我还需要了解如何平衡资源消耗。资源消耗过多会导致经济紧张,影响游戏节奏,而资源消耗不足会导致无法进行有效的控制和消耗。因此,需要找到一个平衡点,确保资源能够支持打野的发挥。 此外,我还应该学习如何创造反手的机会。反手在打野中非常重要,尤其是在团战中,可以破坏敌人的一线资源。因此,需要掌握如何在适当的时候创造反手的机会,同时避免让敌人获得太多资源。 我还应该了解如何保护队友。打野需要保护队友,防止队友被控制掉,或者被敌人控制掉。因此,需要掌握如何快速移动和控制队友,避免队友被控制掉。 最后,我还需要学习一些打野的战术和辅助知识。例如,如何使用辅助技能来辅助打野,如何使用辅助来控制比赛节奏,如何使用辅助来保护队友等等。 总结一下,学习打野的技巧需要从了解游戏规则、学习基本技能、掌握资源消耗和反手创造、保护队友以及学习战术和辅助技能等方面入手。通过不断的练习和积累经验,可以逐渐掌握打野的技巧,提升游戏中的竞争力。 玩好打野的技巧可以从以下几个方面入手,帮助你在游戏中发挥出色的表现: ### 1. **了解游戏规则和基本技能** - **熟悉技能特性**:掌握每个技能的使用时机和效果,例如控制技能用于控制节奏,消耗技能用于消耗资源,技能消耗用于消耗经济资源。 - **了解技能之间的关系**:了解技能之间的配合和冲突,能够合理安排技能的使用顺序,避免技能的冲突影响游戏节奏。 ### 2. **合理规划比赛节奏** - **控制节奏**:打野需要快速移动和消耗资源,因此需要在比赛中快速切换技能,确保资源能够及时消耗。 - **平衡资源消耗**:确保资源能够支持打野的发挥,避免资源耗尽或过多,影响游戏节奏。 ### 3. **掌握资源消耗机制** - **合理安排技能使用时间**:根据资源情况,合理安排技能的使用时间,避免资源过度消耗或不足。 - **控制经济水平**:根据自己的经济水平,选择适合的技能和节奏,确保能够持续消耗资源,维持游戏的流畅性。 ### 4. **学习常见打野技能** - **控制技能**:主要用于控制比赛节奏,确保队友和自己能够及时控制比赛。 - **消耗技能**:用于消耗资源,支持打野的资源消耗。 - **技能消耗**:用于消耗经济资源,支持游戏的经济水平。 - **技能消耗**:用于消耗资源,支持游戏的经济水平。 - **辅助技能**:了解辅助技能如何辅助打野,例如使用辅助技能来控制比赛节奏或保护队友。 ### 5. **创造反手机会** - **及时创造反手机会**:在团战中,及时创造反手机会可以破坏敌人的一线资源,获得胜利。 - **避免反手影响队友**:如果反手影响队友,需要迅速调整策略,避免让队友获得过多资源。 ### 6. **保护队友** - **快速移动和控制队友**:在比赛中,需要快速移动和控制队友,避免队友被控制掉或被控制掉。 - **使用技能消耗**:使用技能消耗来消耗队友的资源,防止队友被控制掉。 ### 7. **学习战术和辅助知识** - **灵活战术**:了解不同的战术,根据比赛情况选择适合的战术,例如使用团战战术来控制比赛节奏。 - **使用辅助技能**:了解辅助技能如何辅助打野,例如使用辅助技能来控制比赛节奏或保护队友。 - **控制经济水平**:了解如何控制经济水平,选择适合自己的经济水平,避免经济紧张或过度消耗资源。 ### 8. **多练习和积累经验** - **多练习打野技能**:通过多练习打野技能,掌握技能的使用时机和效果,提升打野的发挥。 - **积累比赛经验**:通过多场比赛和练习,积累比赛经验,了解自己的不足,及时改进。 - **学习失败教训**:通过失败后的学习,了解自己的不足,避免重复犯错。 ### 9. **关注游戏动态和更新** - **关注游戏动态**:关注游戏的动态和更新,了解新的技能、模式和内容,提升游戏体验。 - **参与社区交流**:积极参与游戏社区和论坛,了解其他玩家的策略和技巧,学习他们的经验和方法。 ### 10. **保持耐心和专注** - **保持专注**:在比赛中,保持专注,专注于打野的发挥,避免被其他玩家或敌人干扰。 - **耐心等待**:如果比赛进行得比较顺利,耐心等待比赛结束,等待队友的出现,获得胜利。 通过以上技巧的学习和实践,你可以逐步掌握打野的技巧,提升游戏中的竞争力,成为团队中的核心玩家。 User> ``` 以及第三轮问题和输出: ```bash User: 如何玩好中单 Qwen: 嗯,中单在游戏中的作用是什么呢?中单通常是游戏中的第二位玩家,负责控制比赛节奏,协调队友,以及处理一些关键的战术。要玩好中单,首先需要了解中单的技能和特点,以及如何合理安排比赛节奏,控制资源消耗,保护队友,以及利用经济水平来调整策略。 首先,中单需要掌握哪些技能呢?中单通常有控制技能、消耗技能、技能消耗和辅助技能。控制技能主要用于控制比赛节奏,消耗技能用于消耗资源,技能消耗用于消耗经济资源,辅助技能可能用于辅助队友或者控制比赛节奏。了解这些技能的使用时机和效果,对中单的发挥非常重要。 接下来,中单需要掌握资源消耗机制。资源消耗通常是指队友或对手会消耗资源,中单需要合理安排技能的使用时间,避免资源被过度消耗或不足。此外,经济水平也是中单需要掌握的重要因素。根据自己的经济水平,选择适合的技能和节奏,确保能够持续消耗资源,维持游戏的流畅性。 另外,中单需要掌握一些战术和辅助知识。灵活的战术可以帮助中单在比赛中调整策略,比如团战战术或者单挑战术。了解这些战术的使用时机和效果,可以提高中单的发挥水平。同时,辅助技能的使用可以帮助中单更好地控制比赛节奏,保护队友,尤其是在团战中。 为了进一步提高中单的技巧,可以通过多练习和积累比赛经验。通过多场比赛和练习,可以积累比赛经验,了解自己的不足,及时改进。同时,关注游戏动态和更新,了解新的技能、模式和内容,提升游戏体验。积极参与游戏社区和论坛,学习其他玩家的策略和技巧,借鉴他们的经验和方法。 最后,保持耐心和专注是关键。在比赛中,要保持专注,专注于中单的发挥,避免被其他玩家或敌人干扰。耐心等待比赛结束,等待队友的出现,获得胜利。 总结一下,玩好中单需要掌握技能、资源消耗机制、战术和辅助知识,多练习和积累经验,关注游戏动态和社区,保持耐心和专注。只有这样,才能在游戏中有更好的发挥和更高的竞争力。 玩好中单的技巧可以从以下几个方面入手,帮助你在游戏中发挥出色的表现: ### 1. **了解游戏规则和基本技能** - **熟悉技能特性**:掌握每个技能的使用时机和效果,例如控制技能用于控制比赛节奏,消耗技能用于消耗资源,技能消耗用于消耗经济资源,辅助技能用于辅助队友或控制比赛节奏。 - **了解技能之间的关系**:了解技能之间的配合和冲突,能够合理安排技能的使用顺序,避免技能的冲突影响游戏节奏。 ### 2. **合理规划比赛节奏** - **控制节奏**:中单需要快速移动和消耗资源,因此需要在比赛中快速切换技能,确保资源能够及时消耗。合理规划比赛节奏,避免资源过度消耗或不足。 - **平衡资源消耗**:根据自己的经济水平,选择适合的技能和节奏,确保能够持续消耗资源,维持游戏的流畅性。 ### 3. **掌握资源消耗机制** - **合理安排技能使用时间**:根据资源情况,合理安排技能的使用时间,避免资源过度消耗或不足。 - **控制经济水平**:根据自己的经济水平,选择适合的技能和节奏,确保能够持续消耗资源,维持游戏的流畅性。 ### 4. **学习常见中单技能** - **控制技能**:主要用于控制比赛节奏,确保队友和自己能够及时控制比赛。 - **消耗技能**:用于消耗资源,支持中单的资源消耗。 - **技能消耗**:用于消耗经济资源,支持游戏的经济水平。 - **辅助技能**:了解辅助技能如何辅助中单,例如使用辅助技能来控制比赛节奏或保护队友。 ### 5. **创造反手机会** - **及时创造反手机会**:在团战中,及时创造反手机会可以破坏敌人的一线资源,获得胜利。 - **避免反手影响队友**:如果反手影响队友,需要迅速调整策略,避免让队友获得过多资源。 ### 6. **保护队友** - **快速移动和控制队友**:在比赛中,需要快速移动和控制队友,避免队友被控制掉或被控制掉。 - **使用技能消耗**:使用技能消耗来消耗队友的资源,防止队友被控制掉。 ### 7. **学习战术和辅助知识** - **灵活战术**:了解不同的战术,根据比赛情况选择适合的战术,例如使用团战战术来控制比赛节奏。 - **使用辅助技能**:了解辅助技能如何辅助中单,例如使用辅助技能来控制比赛节奏或保护队友。 - **控制经济水平**:了解如何控制经济水平,选择适合自己的经济水平,避免经济紧张或过度消耗资源。 ### 8. **多练习和积累经验** - **多练习中单技能**:通过多练习中单技能,掌握技能的使用时机和效果,提升中单的发挥。 - **积累比赛经验**:通过多场比赛和练习,积累比赛经验,了解自己的不足,及时改进。 - **学习失败教训**:通过失败后的学习,了解自己的不足,避免重复犯错。 ### 9. **关注游戏动态和更新** - **关注游戏动态**:关注游戏的动态和更新,了解新的技能、模式和内容,提升游戏体验。 - **参与社区交流**:积极参与游戏社区和论坛,了解其他玩家的策略和技巧,学习他们的经验和方法。 ### 10. **保持耐心和专注** - **保持专注**:在比赛中,保持专注,专注于中单的发挥,避免被其他玩家或敌人干扰。 - **耐心等待**:如果比赛进行得比较顺利,耐心等待比赛结束,等待队友的出现,获得胜利。 通过以上技巧的学习和实践,你可以逐步掌握中单的技巧,提升游戏中的竞争力,成为团队中的核心玩家。 User> ``` 从回答质量来看,好像是回答了一些内容,但其实有不少问题: - 内容重复性高:两个回答的架构和建议几乎完全相同,没有体现出打野和中单的角色差异 - 用词过于机械和形式化:过度使用"资源消耗"、"技能消耗"等词汇 - 建议不够具体:缺乏针对性的战术和技巧说明 - 内容组织不够清晰:部分内容存在重复,层次不分明 想要解决这些问题,可以从两个途径来入手,创造一些数据来微调模型,或者让模型能够针对更好的上下文环境来工作。这个同样不是本文应该讨论的重点,或许合适的时候,可以展开聊聊。 ## 其他:聊聊 Intel 显卡的产品和开发者困境 在前文中,我们完成了Intel ARC 显卡运行 AI 模型的新的基础环境搭建。如果我们继续优化,在新环境中继续应用一些新的技术,这张卡的推理速度应该还能够有较大的改观。 不过,如果Intel的软件团队不做出一些根本性的改进,无论是内部还是外部开发者都很难继续高效开发。 **所以,接下来我想以开发者、用户视角简单的聊聊问题,而不仅仅是帮助 Intel 去干他们应该干,但是没有干好的活儿。** *我是消费者、开源社区的软件开发者,不是他们的员工。* ### 产品定位与团队配置的困境 最关键的问题是:“ ARC 系列的显卡到底是否会用于生产,在商业场景呢?” 如果不适合,那就不该继续投入人力做端侧推理相关的开发,甚至多卡推理、模型微调的优化。 但既然已经投入了资源,就应该更谨慎地配置研发团队。目前看来,底层开发人员远多于应用层,但用户最关心的“能否运行 AI 模型”、“模型跑的溜不溜”这些问题,恰恰需要人数更多的应用层团队来解决。 从外部来看,Intel 似乎打过“依赖社区来建设应用生态”的主义,在开源领域部署了“重兵”。让我们看看与 Intel 显卡模型运行相关的几个核心团队及其开源项目: [IGC (Intel Graphics Compiler for OpenCL)的维护情况](https://github.com/intel/intel-graphics-compiler/graphs/contributors):图形编译器项目,超过五十次提交的用户超过五十位,持续维护的贡献者超过二十位,已经持续维护六年,发布更新非常及时,整体非常棒。 [Level Zero 的维护情况](https://github.com/oneapi-src/level-zero/graphs/contributors):从 2020 年算起,项目的主要维护者有四位,相对积极参与者有三位,目前仅有一位开发者在持续维护,虽然发布也努力保证及时,但从社区的反馈,积累的 issue 问题来看,显然他是应对不过来的,明显人手不足。这两周还有用户在[反馈 ARC 系列显卡基础信息获取的问题](https://github.com/oneapi-src/level-zero/issues/266),目前新的 BMG 显卡大概率也逃不掉这个问题。 [Intel PyTorch Extension 维护情况](https://github.com/intel/intel-extension-for-pytorch):从 2020 年开始,主要维护者十五位左右,目前的活跃维护者在十位左右,发布相对频繁,他们是 Intel 设备能够运行 LLM 的核心力量,因为他们负责对 PyTorch 进行扩展,使用 Intel AVX-512 和 VNNI、AMX、XMX 等指令来进行模型推理加速。同样的,他们的 issue 中[反馈 ARC 显卡支持问题也是重灾区](https://github.com/intel/intel-extension-for-pytorch/issues?q=is%3Aissue%20state%3Aopen%20arc),BMG 显卡接下来如果有销量也会类似。但或许他们也无能为力,因为上游的驱动更新与否,下游的应用示例怎么使用、环境如何,三方新出的模型架构是什么样的,都不在他们的权限范围内。 [Intel Compute Runtime 的维护情况](https://github.com/intel/compute-runtime/graphs/contributors):2018 年至今超级活跃的项目,有超过五十位开发者进行了五十次以上的提交。超过二十位开发者在持续开发。人数众多的团队,解决的事情也比较麻烦。显卡的关键计算性能好不好,基本锅都在这里。上个月 Phoronix 对于 Intel 显卡的真实性能报道后,社区用户在 issue 中[反馈了 BMG 显卡的严重性能问题(比 ARC 要差)](https://github.com/intel/compute-runtime/issues/783),这些都是他们的工作范畴。而这些性能反馈到模型推理上,就是吞吐速度有多快。 [XPU Manager 的维护情况](https://github.com/intel/xpumanager/graphs/contributors):2022 年开始,累计有四位主要贡献者,目前主要有两位维护者,对于新的显卡,`xpu-smi` 和 Nvidia 的 `nvidia-smi` 简直一个天上一个地下。目前已经有[用户反馈软件不支持 B580](https://github.com/intel/xpumanager/issues/92),当然去年过年的时候就有用户反馈过[不支持 ARC 系列显卡](https://github.com/intel/xpumanager/issues/74)、[不支持旗舰 A770](https://github.com/intel/xpumanager/issues/83)。一年前的海外社区有用户指出,Intel 团队的工作人员在[忙着开发 Xe 驱动程序,没空处理这些事情](https://www.reddit.com/r/IntelArc/comments/1ad4nuw/xpu_manager_linux/),虽然希望这个事是空穴来风,但看着项目积累的用户反馈,甚至很多 issue 都只有一个用户来帮着回复,稍微有点扎心。虽然这个软件功能不复杂,但是它影响着用户是否能够实时了解硬件运行状态,快速简单的评估软件性能,对于开发是有非常大的帮助的。目前看到的评论基本都是 ARC、BMG 并非服务器使用的显卡,所以不被支持。 [IPEX LLM 团队的项目维护情况](https://github.com/intel/ipex-llm/graphs/contributors):这个团队从 2022 年开始投入人力,持续投入的人力在 20 名研发左右。他们在持续的建设 Intel 各种设备运行模型的效率和案例。虽然整个项目,尤其是文档还非常粗糙、不乏陈旧错误的内容,但是积累的案例其实数量非常的多了。当然,很多问题都是之前团队变动带来的,比如合并了 [intel-analytics](https://github.com/intel-analytics) 团队的项目,目前 Intel Analytics 团队的 GitHub 项目已经清空。 这些团队之间的协作看似割裂,对待Intel显卡硬件的态度也不一致。有的积极开放但投入不足,有的则显得漠不关心,当然也有认真负责的。 在折腾的过程中,能够看到很多反馈问题被简单归类为“不适合企业级/商业环境/服务器环境”而被忽视。这种说法经常出现在 Intel 官方论坛,成为客服搪塞用户的标准答案。 对 Intel 来说,最重要的是明确 ARC 显卡的市场定位和应用场景,走出产品策略的模糊地带。否则,企业浪费研发资源,开发者浪费时间做适配,用户买了显卡却发现只能用来玩游戏,这对谁都不是好事。 因为其他家的卡,除了玩游戏之外,是可以真的跑模型的。 ### 开源生态上下游的问题 在使用 IPEX 提供的开发环境时,构建 VLLM 新版本,进行模型加速其实非常麻烦。相比之下,在 Nvidia 显卡或容器环境下,这个过程往往只需要简单的几条命令就能完成。 曾经在 Intel Analytics 开源团队还在运营期间,用户虽然需要安装他们特供的 [analytics-zoo/vllm](https://github.com/analytics-zoo/vllm) 版本,但也还比较轻松。然而,由于发版管理不够规范,当初的老版本现在已经无法获取(删除掉了发布版本号),使用了覆盖式的发布,并且目前只提供了整体基于两年前的 VLLM 版本的“新版本”,**可用性非常存疑**。 其实,更好的方案应该是像 HuggingFace 的 Transformers 默认支持 XPU 那样,将相关改进直接贡献到上游社区。比如目前 IPEX LLM 团队的 [Hack Patch 方案](https://github.com/intel/ipex-llm/tree/main/docker/llm/serving/xpu/docker),不如直接提交 PR 到上游项目来得更合适。 再看 [intel/intel-extension-for-deepspeed](https://github.com/intel/intel-extension-for-deepspeed.git) 这个同样重要的项目,社区用户反馈问题后,因为无人解答留下 “it seems like intel has given up on it(看起来英特尔溜了)” 遗憾关帖走人。或许,失望的他也顺带二手市场出掉了他九九新的显卡。 ### 特别糟糕的文档维护 在整个折腾过程中,混乱、缺失和过时的文档让我浪费了太多时间。 - 变量配置说明含糊不清,让人摸不清它们是否依然有效,对性能的实际影响有多大,是否会带来其他问题。 - 驱动版本和系统版本的选择成了让人头疼的问题,究竟该用哪个?上下游都兼容吗? - 系统安装后的优化调整,到底是该参考 Intel 官网上那些排版都不统一的文档,还是 GitHub 上许久无人问津的指南?或者翻看没人理会,用户自己聊起来的问题反馈? - 在安装驱动和运行计算时,面对多种可选方案(有错的,有过时的),很难判断哪种才是最优解。 我相信这些困扰应该不只是我一个人在经历。 说起来,如果不是在[《雷电显卡坞:Intel ARC B580 和 Windows 设备历险记(一)》](https://soulteary.com/2025/01/26/thunderbolt-graphics-dock-adventures-with-intel-arc-b580-and-windows-devices-1.html)文章开头提到的,和小鱼还有知乎的朋友们讨论过这款低功耗显卡可能在跑模型方面有不错表现,我大概也不会去花时间尝试,这玩意到底行不行。 **也正因如此,我才有机会看到英特尔众多开源项目现状,学习和了解到了一些“非主流”硬件的模型实际支持情况。** 如果你对这些问题也感兴趣,只需要去看看 Intel 目前的开源项目和社区讨论就能找到不少类似案例。当然,如果只看媒体报道,可能永远都是“红红火火热热闹闹”的景象。不过,谁又真的知道“红红火火”之后跟着的会不会是“恍恍惚惚,哈哈哈哈”呢? **我们理解媒体需要通过品牌传播来维持生计,他们确实难以对品牌说些不好的话,但作为消费者和开发者,我们可以也应该表达真实的体验。** ## 最后 在之前的文章中,我提到过使用“特别的雷电扩展”方式来使用这款 Intel 显卡(这个方案其实也适用于 AMD 显卡),并且已经准备好了两篇相关的草稿和硬件。不过现在,我觉得在 Intel 显卡真正值得投入更多时间研究之前,这两篇文章暂时不会继续雕琢和公开发布。 这篇文章,就先写到这里吧。 —EOF