如何构建一个支持GPU的Llamafile容器

用CPU玩那些大型的语言模型确实挺有意思的,但看着电脑一个字一个字地慢慢显示结果,那股兴奋劲儿很快就过去了。让这些语言模型软件在GPU上跑起来可能会有点麻烦,因为这得看你的系统和硬件支不支持。我这篇文章就是想告诉你,怎么在你的NVIDIA RTX 2060上跑起来llamafile这个软件。里面的例子会用到llamafile、NVIDIA CUDA、Ubuntu 22.04操作系统还有Docker这几个工具。

先检查一下你的GPU和NVIDIA CUDA软件

首先得确认一下你的CUDA装了没有。NVIDIA有个工具,能显示你的GPU和CUDA的状态。

% nvidia-smi

+---------------------------------------------------------------------------------------+
| NVIDIA-SMI 535.154.05             Driver Version: 535.154.05   CUDA Version: 12.2     |
|-----------------------------------------+----------------------+----------------------+
| GPU  Name                 Persistence-M | Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp   Perf          Pwr:Usage/Cap |         Memory-Usage | GPU-Util  Compute M. |
|                                         |                      |               MIG M. |
|=========================================+======================+======================|
|   0  NVIDIA GeForce RTX 2060        Off | 00000000:01:00.0  On |                  N/A |
| N/A   44C    P8               8W /  90W |   1322MiB /  6144MiB |      6%      Default |
|                                         |                      |                  N/A |
+-----------------------------------------+----------------------+----------------------+

如果你看到的输出和这个差不多,那就说明你的CUDA已经装好了。别忘了看一眼CUDA的版本号。这个版本号还有你的显卡的计算能力,会决定你构建镜像时得用哪个基础镜像。NVIDIA有提供一张图表(https://developer.nvidia.com/cuda-gpus#compute),上面列出了他们家各种设备的计算能力。你可以根据你的设备型号去查对应的菜单选项。比如说,你要是用的RTX 2060这款显卡,就在图表里找到它对应的那一项。

配置Docker

NVIDIA Container Toolkit这个工具能让Docker用上GPU的能力。NVIDIA也给出了安装Container Toolkit的详细指南。但如果你等不及想看简化版的,我这就来给你说说简化后的步骤。

% distribution=$(. /etc/os-release;echo $ID$VERSION_ID) \
      && curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg \
      && curl -s -L https://nvidia.github.io/libnvidia-container/$distribution/libnvidia-container.list | \
            sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
            sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list

% sudo apt-get update

% sudo apt-get install -y nvidia-docker2

在Linux系统里,你得更新这个文件/etc/docker/daemon.json来设置Docker Engine后台服务,并且把NVIDIA的容器运行时加进去。要是你的系统里没有daemon.json这个文件呢,你就新建一个,内容大概是这样的:

{
    "runtimes": {
        "nvidia": {
            "path": "/usr/bin/nvidia-container-runtime",
            "runtimeArgs": []
        }
    }
}

这样设置好之后,重启Docker以应用更改。你的Docker就能用上NVIDIA的GPU加速功能了。

% sudo systemctl restart docker

测试运行时是否工作。

% $ docker run --rm --gpus all nvidia/cuda:11.6.2-base-ubuntu20.04 nvidia-smi

如果工作正常,你应该看到类似的结果。

+---------------------------------------------------------------------------------------+
| NVIDIA-SMI 535.154.05             Driver Version: 535.154.05   CUDA Version: 12.2     |
|-----------------------------------------+----------------------+----------------------+
| GPU  Name                 Persistence-M | Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp   Perf          Pwr:Usage/Cap |         Memory-Usage | GPU-Util  Compute M. |
|                                         |                      |               MIG M. |
|=========================================+======================+======================|
|   0  NVIDIA GeForce RTX 2060        Off | 00000000:01:00.0  On |                  N/A |
| N/A   44C    P8              10W /  90W |   1530MiB /  6144MiB |      6%      Default |
|                                         |                      |                  N/A |
+-----------------------------------------+----------------------+----------------------+

来聊聊怎么构建Llamafile的镜像吧

咱们得一步步来分析这个Dockerfile。我会详细解释我做每个选择的原因。Dockerfile用的是多阶段构建的方法,咱们先从编译llamafile的二进制文件开始说起。

FROM debian:trixie as builder

WORKDIR /download

RUN mkdir out && \
    apt-get update && \
    apt-get install -y curl git gcc make && \
    git clone https://github.com/Mozilla-Ocho/llamafile.git  && \
    curl -L -o ./unzip https://cosmo.zip/pub/cosmos/bin/unzip && \
    chmod 755 unzip && mv unzip /usr/local/bin && \
    cd llamafile && make -j8 && \
    make install PREFIX=/download/out

这段Dockerfile是用来编译llamafile的二进制文件的。就像很多开源项目一样,llamafile非常活跃,几乎每周都有新功能更新和bug修复。所以我选择从源代码来编译llamafile,而不是直接用现成的二进制文件。另外,llamafile还能被编译成一个包含模型的单个可执行文件,但为了保持简单,我就没包括这一步。

接下来,多阶段构建的下一步是创建一个运行llamafile的镜像,这个镜像会用到主机上的GPU。NVIDIA提供了适合像llamafile这种GPU应用的CUDA基础镜像。前面我们记下了CUDA的版本和驱动程序的版本,NVIDIA也特别指出了:

"为了运行CUDA应用程序,系统应该具有支持CUDA的GPU和与用于构建应用程序本身的CUDA Toolkit兼容的NVIDIA显示驱动程序。如果应用程序依赖于库的动态链接,则系统还应该具有正确版本的这些库。"

基础的NVIDIA CUDA镜像得和你的主机上的CUDA版本对得上号。比如说,你手里有个挺新的显卡,那你就应该选一个最新的主机平台镜像。你还能挑挑不同的Linux发行版,决定是用那种带软件开发工具链的开发镜像,还是用那种拿来部署现成应用的运行时版本。

不过得注意啊,我这篇文章里头做的实验,用的GeForce RTX 2060显卡和最新的CUDA镜像不兼容。我们其实可以用老一点的镜像,但是NVIDIA的CUDA仓库里头维护了各种不同CUDA版本的Dockerfiles。所以我们可以为我们自己的CUDA版本和Linux发行版定制一个镜像。如果你想自己来构建一个CUDA镜像,那就去下载对应的Dockerfile,然后动手构建吧:

% docker build -t cuda12.2-base-ubuntu-22.04 .

这部分的Dockerfile是用来安装和设置CUDA工具包的,这对于让llamafile在CUDA基础镜像里用上GPU功能是必不可少的。你得用一个跟你的CUDA版本和Linux发行版相匹配的基础镜像来替换。另外,这里还创建了一个用户,这样容器就不会以root用户的身份运行了,安全性更高。

FROM cuda-12.2-base-ubuntu-22.04 as out

RUN apt-get update && \
    apt-get install -y linux-headers-$(uname -r) && \
    apt-key del 7fa2af80 && \
    apt-get update && \
    apt-get install -y clang && \
    apt-get install -y cuda-toolkit && \
    addgroup --gid 1000 user && \
    adduser --uid 1000 --gid 1000 --disabled-password --gecos "" user

USER user

接下来的步骤是从构建器镜像中复制llamafile的二进制文件、手册页,还有LLM模型。在这个例子里,LLM模型codellama-7b-instruct.Q4_K_M.gguf是从Hugging Face上下载的。你也可以用任何和llamafile(或者llama.cpp)兼容的GGUF格式的模型。要记住,llamafile是作为服务器启动的,它包含了一个OPENAI API的接口,而且通过-ng 9999这个参数来启用GPU功能。

WORKDIR /usr/local

COPY --from=builder /download/out/bin ./bin
COPY --from=builder /download/out/share ./share/man
COPY codellama-7b-instruct.Q4_K_M.gguf /model/codellama-7b-instruct.Q4_K_M.gguf

# 不要写日志文件。
ENV LLAMA_DISABLE_LOGS=1

# 暴露8080端口。
EXPOSE 8080

# 设置入口点。
ENTRYPOINT ["/bin/sh", "/usr/local/bin/llamafile"]

# 设置默认命令。
CMD ["--server", "--nobrowser", "-ngl", "9999","--host", "0.0.0.0", "-m", "/model/codellama-7b-instruct.Q4_K_M.gguf"]

构建并标记镜像。

% docker build -t llamafile-codellama-gpu .

这是完整的Dockerfile。

FROM debian:trixie as builder

WORKDIR /download

RUN mkdir out && \
    apt-get update && \
    apt-get install -y curl git gcc make && \
    git clone https://github.com/Mozilla-Ocho/llamafile.git  && \
    curl -L -o ./unzip https://cosmo.zip/pub/cosmos/bin/unzip && \
    chmod 755 unzip && mv unzip /usr/local/bin && \
    cd llamafile && make -j8 && \
    make install PREFIX=/download/out

FROM cuda-12.2-base as out

RUN apt-get update && \
    apt-get install -y linux-headers-$(uname -r) && \
    apt-key del 7fa2af80 && \
    apt-get update && \
    apt-get install -y clang && \
    apt-get install -y cuda-toolkit && \
    addgroup --gid 1000 user && \
    adduser --uid 1000 --gid 1000 --disabled-password --gecos "" user

USER user

WORKDIR /usr/local

COPY --from=builder /download/out/bin ./bin
COPY --from=builder /download/out/share ./share/man
COPY codellama-7b-instruct.Q4_K_M.gguf /model/codellama-7b-instruct.Q4_K_M.gguf

# 不要写日志文件。
ENV LLAMA_DISABLE_LOGS=1

# 暴露8080端口。
EXPOSE 8080

# 设置入口点。
ENTRYPOINT ["/bin/sh", "/usr/local/bin/llamafile"]

# 设置默认命令。
CMD ["--server", "--nobrowser", "-ngl", "9999","--host", "0.0.0.0", "-m", "/model/codellama-7b-instruct.Q4_K_M.gguf"]

享受性能提升

咱们可以利用continue.dev这个开源的LLM编码VSCode插件,来试试看给llamafile开启GPU后搭配codellama-7b-instruct.Q4_K_M.gguf模型的效果。Continue.dev这个插件兼容任何支持OpenAI API的LLM。如果你想在装有GPU的笔记本上用服务器模式运行llamafile,同时在M2 Mac mini上使用VSCode,那下面这些步骤就能帮到你。

提示:

"深度优先搜索URL并打印页面作为树。"

补全:

import requests
from bs4 import BeautifulSoup
def depth_first_search(url):
  """深度优先搜索URL并打印页面作为树。"""
    # 初始化一个集合来跟踪访问过的URL
    visited = set()
    # 创建一个队列来存储要访问的URL
    queue = [url]
    while queue:
        # 从队列中获取下一个URL
        url = queue.pop(0)
        # 如果URL尚未访问,则访问它并将其子项添加到队列中
        if url not in visited:
            response = requests.get(url)
            soup = BeautifulSoup(response.text, 'html.parser')
            for link in soup.find_all('a'):
                queue.append(link.get('href'))
            print(f"{url} -> {', '.join(queue)}")
            visited.add(url)

首先,我先在CPU上跑了跑llamafile的可执行文件,作为性能对比的基准。

% llamafile --server --host 0.0.0.0 -m codellama-7b-instruct.Q4_K_M.gguf

用CPU跑的话,提示评估的速度是每秒24个标记,整个补全过程得花上超过一分钟的时间。

print_timings: prompt eval time =    4963.79 ms /   121 tokens (   41.02 ms per token,    24.38 tokens per second)
print_timings:        eval time =   64191.60 ms /   472 runs   (  136.00 ms per token,     7.35 tokens per second)
print_timings:       total time =   69155.39 ms

然后呢,我开启了GPU,又运行了一遍llamafile的可执行文件。

 % llamafile --server --host 0.0.0.0 -ngl 9999 -m codellama-7b-instruct.Q4_K_M.gguf

用上GPU之后,提示评估的速度比用CPU快了17倍,每秒能处理426个标记。整个补全过程在11秒内就搞定了,响应时间明显提升了不少。

print_timings: prompt eval time =     283.92 ms /   121 tokens (    2.35 ms per token,   426.18 tokens per second)
print_timings:        eval time =   11134.10 ms /   470 runs   (   23.69 ms per token,    42.21 tokens per second)
print_timings:       total time =   11418.02 ms

后来我又试了试运行开了GPU功能的llamafile容器,想看看容器化会不会对性能有啥影响。

% docker run -it --gpus all --runtime nvidia -p 8111:8080 llamafile-codellama-gpu

可以看出,容器的性能并没有下降,因为容器其本质上就是一个进程,下面的测量结果反而比单纯启用GPU的可执行文件还要稍微好那么一点儿。这个我感觉不是特别准确,应该是差不多才对。

print_timings: prompt eval time =     257.56 ms /   121 tokens (    2.13 ms per token,   469.80 tokens per second)
print_timings:        eval time =   11498.98 ms /   470 runs   (   24.47 ms per token,    40.87 tokens per second)
print_timings:       total time =   11756.53 ms

总结一下哈

给llamafile加上GPU支持,一下子就让它从一个实验性的玩具变成了软件工具箱里的实用工具。而且,把LLM容器化了之后,大家就不用安装和下载那些二进制文件,就能直接跑LLM了。我们可以直接从仓库拉取LLM,用很少的设置就能启动。另外,容器化还为在各种编排框架里部署LLM提供了新的可能性,你觉得呢?

相关推荐
paixiaoxin5 分钟前
CV-OCR经典论文解读|An Empirical Study of Scaling Law for OCR/OCR 缩放定律的实证研究
人工智能·深度学习·机器学习·生成对抗网络·计算机视觉·ocr·.net
OpenCSG26 分钟前
CSGHub开源版本v1.2.0更新
人工智能
weixin_5152024927 分钟前
第R3周:RNN-心脏病预测
人工智能·rnn·深度学习
Altair澳汰尔30 分钟前
数据分析和AI丨知识图谱,AI革命中数据集成和模型构建的关键推动者
人工智能·算法·机器学习·数据分析·知识图谱
机器之心1 小时前
图学习新突破:一个统一框架连接空域和频域
人工智能·后端
AI视觉网奇1 小时前
人脸生成3d模型 Era3D
人工智能·计算机视觉
call me by ur name1 小时前
VLM--CLIP作分类任务的损失函数
人工智能·机器学习·分类
Python机器学习AI1 小时前
分类模型的预测概率解读:3D概率分布可视化的直观呈现
算法·机器学习·分类
吃个糖糖1 小时前
34 Opencv 自定义角点检测
人工智能·opencv·计算机视觉
禁默1 小时前
2024年图像处理、多媒体技术与机器学习
图像处理·人工智能·microsoft