Skip to content

Latest commit

 

History

History
436 lines (372 loc) · 18.4 KB

README_CN.md

File metadata and controls

436 lines (372 loc) · 18.4 KB

xFasterTransformer

English | 简体中文

xFasterTransformer为大语言模型(LLM)在CPU X86平台上的部署提供了一种深度优化的解决方案,支持多CPU节点之间的分布式部署方案,使得超大模型在CPU上的部署成为可能。此外,xFasterTransformer提供了C++和Python两种API接口,涵盖了从上层到底层的接口调用,易于用户使用并将xFasterTransformer集成到自有业务框架中。

目录

模型概览

大型语言模型(LLM)的发展速度非常快,在许多人工智能场景中得到了广泛的应用。xFasterTransformer 充分利用了至强平台的硬件能力,在单颗CPU和多颗CPU/多节点上实现了 LLM 推理的高性能和高可扩展性。

xFasterTransformer 提供了一系列 C++ 和 Python 应用程序接口,终端用户可将 xFasterTransformer 直接集成到自己的解决方案或服务中。此外,xFT还提供了多种示例代码来演示使用方法。包括供用户进行性能测试的测试代码和脚本,以及通过网页模式搭建常用 LLM 模型服务的示例。

支持的模型

模型 框架 分布式支持
PyTorch C++
ChatGLM
ChatGLM2
ChatGLM3
Llama
Llama2
Llama3
Baichuan1
Baichuan2
QWen
QWen2
SecLLM(YaRN-Llama)
Opt
Deepseek-coder
gemma
gemma-1.1
codegemma

支持的数据类型

  • FP16
  • BF16
  • INT8
  • W8A8
  • INT4
  • NF4
  • BF16_FP16
  • BF16_INT8
  • BF16_W8A8
  • BF16_INT4
  • BF16_NF4
  • W8A8_INT8
  • W8A8_int4
  • W8A8_NF4

目录

xFasterTransformer 文档和Wiki提供了以下资源:

  • xFasterTransformer 简介。
  • C++ 和 PyTorch 上层和底层接口的全面 API 参考资料。
  • 在 C++ 和 PyTorch 中使用 xFasterTransformer 的实用 API 示例。

安装

使用 PyPI

pip install xfastertransformer

使用 Docker

docker pull intel/xfastertransformer:latest

使用命令运行 docker (假设模型文件位于 /data/ 目录):

docker run -it \
    --name xfastertransformer \
    --privileged \
    --shm-size=16g \
    -v /data/:/data/ \
    -e "http_proxy=$http_proxy" \
    -e "https_proxy=$https_proxy" \
    intel/xfastertransformer:latest

注意!!!: 如果在多进程模式下运行时发生bus error,请增大"--shm-size"。docker默认限制共享内存大小为64MB,而我们的实现使用大量的共享内存来获得更好的性能。

从源码构建

准备环境

手动操作
  • PyTorch v2.3 (使用 PyTorch API 时需要,但使用 C++ API 时不需要。)

    pip install torch --index-url https://download.pytorch.org/whl/cpu
  • 对于 GPU 版本的 xFT,由于 DPC++ 要求 ABI=1,因此需要安装 torch-whl-list 中 ABI=1 的 torch==2.3.0+cpu.cxx11.abi

安装依赖的库

请安装所依赖的libnuma库:

  • CentOS: yum install libnuma-devel
  • Ubuntu: apt-get install libnuma-dev
如何编译
  • 使用 'CMake'
    # 构建 xFasterTransformer
    git clone https://github.com/intel/xFasterTransformer.git xFasterTransformer
    cd xFasterTransformer
    git checkout <latest-tag>
    # 如果使用python示例,请确保已经安装torch。
    mkdir build && cd build
    cmake ..
    make -j
  • 使用 python setup.py
    # 构建Build xFasterTransformer库和C++示例。
    python setup.py build
    
    # 安装xFastertransformer到pip环境中。
    # 注意:在安装之前请运行 `python setup.py build`!
    python setup.py install

xFasterTransformer 支持的模型格式与 Huggingface 有所不同,但与 FasterTransformer 的格式兼容。

  1. 首先下载 huggingface 格式的模型。

  2. 然后,使用 xfastertransformer 中的模型转换模块将模型转换为 xFasterTransformer 格式。如果没有提供输出目录,转换后的模型将被默认放置到 ${HF_DATASET_DIR}-xft.

    python -c 'import xfastertransformer as xft; xft.LlamaConvert().convert("${HF_DATASET_DIR}","${OUTPUT_DIR}")'
    

    PS: 由于模型文件和 transformers 版本之间可能存在兼容性问题,请选择相应的 transformers 版本。

    支持的模型转换列表:

    • LlamaConvert
    • YiConvert
    • GemmaConvert
    • ChatGLMConvert
    • ChatGLM2Convert
    • ChatGLM3Convert
    • OPTConvert
    • BaichuanConvert
    • QwenConvert
    • Qwen2Convert
    • DeepseekConvert

API 用法

更多详情,请参阅 API 文档和 示例.

Python API(PyTorch)

首先,请安装依赖项。

  • Python 依赖项
    pip install -r requirements.txt
    PS: 由于模型文件和 transformers版本之间可能存在兼容性问题,请选择适当的 transformers版本。
  • oneCCL (用于多进程)
    安装 oneCCL 并设置环境。请参阅准备环境.

xFasterTransformer 的 Python API 与transformers类似,也支持transformers的streamer来实现流式输出。在示例中,我们使用transformers将输入文字进行编码,生成token id。

import xfastertransformer
from transformers import AutoTokenizer, TextStreamer
# 假设huggingface格式的模型目录为`/data/chatglm-6b-hf`,转换后模型的目录为`/data/chatglm-6b-xft`.
MODEL_PATH="/data/chatglm-6b-xft"
TOKEN_PATH="/data/chatglm-6b-hf"

INPUT_PROMPT = "Once upon a time, there existed a little girl who liked to have adventures."
tokenizer = AutoTokenizer.from_pretrained(TOKEN_PATH, use_fast=False, padding_side="left", trust_remote_code=True)
streamer = TextStreamer(tokenizer, skip_special_tokens=True, skip_prompt=False)

input_ids = tokenizer(INPUT_PROMPT, return_tensors="pt", padding=False).input_ids
model = xfastertransformer.AutoModel.from_pretrained(MODEL_PATH, dtype="bf16")
generated_ids = model.generate(input_ids, max_length=200, streamer=streamer)

C++ API

SentencePiece 可用于文本编码和解码。

#include <vector>
#include <iostream>
#include "xfastertransformer.h"
// ChatGLM token ids for prompt "Once upon a time, there existed a little girl who liked to have adventures."
std::vector<int> input(
        {3393, 955, 104, 163, 6, 173, 9166, 104, 486, 2511, 172, 7599, 103, 127, 17163, 7, 130001, 130004});

// 假设转换后的模型目录为`/data/chatglm-6b-xft`.
xft::AutoModel model("/data/chatglm-6b-xft", xft::DataType::bf16);

model.config(/*max length*/ 100, /*num beams*/ 1);
model.input(/*input token ids*/ input, /*batch size*/ 1);

while (!model.isDone()) {
    std::vector<int> nextIds = model.generate();
}

std::vector<int> result = model.finalize();
for (auto id : result) {
    std::cout << id << " ";
}
std::cout << std::endl;

如何运行

建议预加载 libiomp5.so 以获得更好的性能。

  • [推荐] 如果已安装 xfastertransformer 的 Python wheel 包,请运行 export $(python -c 'import xfastertransformer as xft; print(xft.get_env())')
  • 如果从源代码构建 xFasterTransformer,成功构建后 libiomp5.so 文件将在 3rdparty/mkl/lib 目录下。

单进程

xFasterTransformer 会自动检查 MPI 环境,或者使用 SINGLE_INSTANCE=1 环境变量强制停用 MPI。

多进程

命令行调用

使用 MPI 在多进程模式下运行,请先安装 oneCCL。

  • oneCCL 安装

    • 如果您从源代码编译了 xfastertransformer,则在编译时会在3rdparty目录安装 oneCCL。
      source ./3rdparty/oneccl/build/_install/env/setvars.sh
      
    • [推荐] 使用提供的脚本从源代码中构建。
      cd 3rdparty
      sh prepare_oneccl.sh
      source ./oneccl/build/_install/env/setvars.sh
    • 通过 Intel® oneAPI Base Toolkit安装 oneCCL。(注意:建议使用 2023.x 及以下版本。) 并通过以下方式提供环境:
      source /opt/intel/oneapi/setvars.sh
      
  • 下面是一个本地环境的运行方式示例。

    # 或者手动预加载 export LD_PRELOAD=libiomp5.so
    export $(python -c 'import xfastertransformer as xft; print(xft.get_env())')
    OMP_NUM_THREADS=48 mpirun \
      -n 1 numactl -N 0  -m 0 ${RUN_WORKLOAD} : \
      -n 1 numactl -N 1  -m 1 ${RUN_WORKLOAD} 

代码实现

更多详情,请参阅示例。

Python

model.rank 可以获得进程的编号,model.rank == 0 是主进程。 对于从属进程,加载模型后只需要做 model.generate()。输入和生成配置将自动同步。

model = xfastertransformer.AutoModel.from_pretrained("/data/chatglm-6b-xft", dtype="bf16")

# Slave
while True:
    model.generate()
C++

model.getRank()可以获取进程的编号,model.getRank() == 0 是主进程。 对于从属进程,可以向 model.config()model.input 输入任何值,因为主进程的值将被同步。

xft::AutoModel model("/data/chatglm-6b-xft", xft::DataType::bf16);

// Slave
while (1) {
    model.config();
    std::vector<int> input_ids;
    model.input(/*input token ids*/ input_ids, /*batch size*/ 1);

    while (!model.isDone()) {
        model.generate();
    }
}

本仓库中提供了基于 Gradio的网页demo。现在支持 ChatGLM、ChatGLM2 和 Llama2 模型。

  • 准备模型.
  • 安装依赖项
    pip install -r examples/web_demo/requirements.txt
    PS: 由于模型文件和 transformers版本之间可能存在兼容性问题,请选择适当的 transformers版本。
  • 运行与模型相对应的脚本。网络服务器启动后,在浏览器中打开输出 URL 以使用演示程序。请指定模型和tokenizer目录的路径以及数据类型。transformer的tokenizer用于对文本进行编码和解码,因此${TOKEN_PATH}指的是 huggingface 模型目录。此演示还支持多进程。
# 推荐预加载`libiomp5.so`来获得更好的性能。
# `libiomp5.so`文件会位于编译后`3rdparty/mklml/lib`文件夹中。
# 或者手动预加载LD_PRELOAD=libiomp5.so manually, `libiomp5.so`文件会位于编译后`3rdparty/mkl/lib`文件夹中
export $(python -c 'import xfastertransformer as xft; print(xft.get_env())')
python examples/web_demo/ChatGLM.py \
                      --dtype=bf16 \
                      --token_path=${TOKEN_PATH} \
                      --model_path=${MODEL_PATH}

服务

vLLM

vllm-xft项目创建了vLLM的一个分支版本,该版本集成了xFasterTransformer后端以提高性能,同时保持了与官方vLLM大多数功能的兼容性。详细信息请参考此链接

Install

pip install vllm-xft

注意:请不要在环境中同时安装 vllm-xftvllm 。虽然包名不同,但实际上它们会互相覆盖。

兼容OpenAI-API的服务

注意:需要预加载 libiomp5

# 通过以下命令或手动设置 LD_PRELOAD=libiomp5.so 预加载 libiomp5.so
export $(python -c 'import xfastertransformer as xft; print(xft.get_env())')

python -m vllm.entrypoints.openai.api_server \
        --model ${MODEL_PATH} \
        --tokenizer ${TOKEN_PATH} \
        --dtype bf16 \
        --kv-cache-dtype fp16 \
        --served-model-name xft \
        --port 8000 \
        --trust-remote-code

对于分布式模式,请使用 python -m vllm.entrypoints.slave 作为从节点,并确保从节点的参数与主节点一致。

# 通过以下命令或手动设置 LD_PRELOAD=libiomp5.so 预加载 libiomp5.so
export $(python -c 'import xfastertransformer as xft; print(xft.get_env())')

OMP_NUM_THREADS=48 mpirun \
        -n 1 numactl --all -C 0-47 -m 0 \
          python -m vllm.entrypoints.openai.api_server \
            --model ${MODEL_PATH} \
            --tokenizer ${TOKEN_PATH} \
            --dtype bf16 \
            --kv-cache-dtype fp16 \
            --served-model-name xft \
            --port 8000 \
            --trust-remote-code \
        : -n 1 numactl --all -C 48-95 -m 1 \
          python -m vllm.entrypoints.slave \
            --dtype bf16 \
            --model ${MODEL_PATH} \
            --kv-cache-dtype fp16

FastChat

xFasterTransformer 是 FastChat的官方推理后端。详细信息请参考 FastChat 中的 xFasterTransformerFastChat 服务

MLServer

MLServer 服务示例 支持 REST 和 gRPC 接口,并具有自适应批处理功能,可即时将推理请求分组。

提供的Benchmark脚本可快速获得模型推理性能。

  • 准备模型.
  • 安装依赖项,包括 oneCCL 和 python 依赖项。
  • 进入 benchmark 文件夹并运行 run_benchmark.sh。更多信息请参阅 Benchmark README

备注!!!: 系统和 CPU 配置可能不同。为获得最佳性能,请尝试根据测试环境修改 OMP_NUM_THREADS、数据类型和内存节点数(使用 numactl -H 检查内存节点)。

技术支持

论文发表

如果你觉得xFT对你的研究有帮助,请引用:

@article{he2024distributed,
  title={Distributed Inference Performance Optimization for LLMs on CPUs},
  author={He, Pujiang and Zhou, Shan and Li, Changqing and Huang, Wenhuan and Yu, Weifei and Wang, Duyi and Meng, Chen and Gui, Sheng},
  journal={arXiv preprint arXiv:2407.00029},
  year={2024}
}

and

@inproceedings{he2024inference,
  title={Inference Performance Optimization for Large Language Models on CPUs},
  author={He, Pujiang and Zhou, Shan and Huang, Wenhuan and Li, Changqing and Wang, Duyi and Guo, Bin and Meng, Chen and Gui, Sheng and Yu, Weifei and Xie, Yi},
  booktitle={ICML 2024 Workshop on Foundation Models in the Wild}
}

问题与回答

  • : xFasterTransformer 可以在 Intel® Core™ CPU 上运行吗?
    : 不可以。xFasterTransformer 需要 AMX 和 AVX512 指令集的支持,而Intel® Core™ CPU不支持这些指令集。

  • : xFasterTransformer 可以在 Windows 系统上运行吗?
    : 不支持 Windows,所有兼容性测试都只在 Linux 上进行,因此建议使用 Linux。

  • : 通过 oneAPI 安装了最新版本的 oneCCL 后,在多进程模式下运行时,为什么程序会卡死或出错?
    : 请尝试将 oneAPI 降级到 2023.x 或更低版本,或使用提供的脚本从源代码安装 oneCCL。

  • : 为什么使用两个 CPU 运行程序的性能比使用单个 CPU 运行程序的性能要低得多?
    : 以这种方式运行会导致程序进行许多不必要的跨CPU通信,严重影响性能。如果需要跨CPU部署,可考虑在多进程模式下运行,在每个CPU上部署一个进程。

  • :以单进程运行时性能正常,但为什么使用 MPI 运行多进程性能很慢,CPU 利用率很低?
    :这是因为通过 MPI 启动的程序读取的是 OMP_NUM_THREADS=1,无法从环境中正确获取相应的值。有必要根据实际情况手动设置 OMP_NUM_THREADS 的值。

  • : 为什么在转换已支持的模型时仍会遇到错误?
    : 尝试将 transformer 降级到合适的版本,如 requirements.txt 中指定的版本。这是因为不同版本的 Transformer 可能会更改某些变量的名称。