Modal 平台 GPU 环境下运行 Manim
在本教程中,我们将演示如何配置一个 Modal 应用,使其在带 GPU(例如 A10G)的容器中运行 Manim 脚本进行渲染。整个过程包含以下关键步骤:
- 选择合适的基础镜像:使用 NVIDIA 提供的 CUDA 开发镜像(如
nvidia/cuda:12.2.0-devel-ubuntu22.04
),确保容器中具备必要的 CUDA 库,同时添加 Python 3.10 环境。 - 安装系统依赖:由于 Manim 的文本渲染组件 ManimPango 需要从源码构建(Linux 下无预编译 wheel),因此需要提前安装 C/C++ 编译器、Python 开发头文件、
pkg-config
、Pango/Cairo 开发库等。此外,为避免安装 tzdata 时进入交互式配置,还需设置相关环境变量。 - 安装 Python 包:通过 pip 安装 Manim 及其依赖(如 numpy、moviepy、requests、latex 等),并单独安装 manimpango 以保证 ManimPango 构建成功。
- 挂载本地脚本目录:利用 Modal 的目录挂载功能,将本地存放 Manim 脚本的目录挂载到容器内,确保每次运行时能获取最新代码。
- 安装 FFmpeg 和 LaTeX 环境:Manim 渲染需要 FFmpeg 来合成视频文件,并使用 LaTeX 环境(例如 texlive-full)处理数学公式。Ubuntu 22.04 中的 FFmpeg 通常支持 NVIDIA 硬件加速(NVENC),方便利用 GPU 进行编码。
- 定义 Modal 应用和 GPU 函数:使用
@app.function(gpu="A10G")
指定函数运行时分配 A10G GPU,同时在函数内通过subprocess
检查 FFmpeg 是否启用了 NVENC,再读取并执行挂载在容器内的 Manim 脚本。
下文给出完整的代码示例,并附上详细说明和参考来源信息。
1. 配置支持 CUDA 的基础镜像
为了充分利用 GPU 资源,我们选择 NVIDIA 官方的 CUDA 开发镜像 nvidia/cuda:12.2.0-devel-ubuntu22.04
。该镜像内预装了 CUDA 12.2 的相关库,适用于需要 GPU 加速的任务。同时通过 add_python="3.10"
安装 Python 环境。设置环境变量 DEBIAN_FRONTEND=noninteractive
与 TZ=Asia/Shanghai
可避免 tzdata 在安装时弹出交互提示,从而保证镜像构建的自动化。
import subprocess
import modal
image = (
modal.Image.from_registry("nvidia/cuda:12.2.0-devel-ubuntu22.04", add_python="3.10")
.env({"DEBIAN_FRONTEND": "noninteractive", "TZ": "Asia/Shanghai"})
参考说明:选择 CUDA 镜像是为了确保容器中拥有 GPU 加速所必需的 CUDA 库;同时设置时区和非交互模式(Modal Docs)有助于自动化安装过程。
2. 安装系统依赖与 Python 包
Manim 在渲染过程中使用 ManimPango(Pango 的 Python 绑定),但 Linux 下并没有预编译的 wheel 包,因此需要在构建前安装编译工具和相关系统库。安装内容包括:
- tzdata:设置时区,避免交互式提示。
- build-essential、python3-dev、pkg-config:编译 C/C++ 扩展时必备。
- libcairo2-dev、libpango1.0-dev、clang:支持 Pango/Cairo 文本渲染(参见 ManimCommunity/ManimPango)。
- ffmpeg、ghostscript、dvisvgm、texlive-full:FFmpeg 用于视频编码(Ubuntu 22.04 中通常支持 NVENC),而 LaTeX 环境(texlive-full)确保 Tex/MathTex 能正常渲染数学公式。
同时,升级 pip、setuptools 和 wheel 确保后续安装顺利,然后利用 pip 分别安装 manim
、numpy
、latex
、moviepy
、requests
及 manimpango
。
.apt_install("tzdata")
.run_commands("ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' > /etc/timezone")
.apt_install("build-essential", "ffmpeg", "ghostscript", "dvisvgm", "texlive-full")
.apt_install("python3-dev", "pkg-config")
.apt_install("libcairo2-dev", "libpango1.0-dev", "clang")
.run_commands("pip install --upgrade pip setuptools wheel")
.pip_install("numpy", "manim", "latex", "moviepy", "requests")
.pip_install("manimpango")
背景说明:
- ManimPango 的构建需要依赖 Pango 和 Cairo 的开发库,安装这些依赖能确保 pip 构建过程中不会报错(参考 3b1b/manim issue)。
- FFmpeg 安装后可利用 NVIDIA NVENC 编码器对视频进行硬件加速;Ubuntu 22.04 默认的 ffmpeg 包通常已包含 NVENC 支持(参见 3b1b/manim 官方说明)。
- texlive-full 能够完整支持 LaTeX 渲染需求,适用于 Manim 中的数学公式和文本渲染。
3. 添加本地脚本目录挂载
为了便于管理和实时更新 Manim 脚本,我们将本地的 scripts
目录挂载到容器的 /scripts
目录中。这样,无需重新构建镜像即可更新渲染场景。
.add_local_dir("scripts", "/scripts")
)
提示:Modal 支持使用
add_local_dir
方法挂载本地目录,确保在函数运行时容器能读取最新的脚本文件。
4. 定义 Modal 应用和 GPU 渲染函数
接下来,我们定义 Modal 应用和一个 GPU 渲染函数。该函数主要包括以下步骤:
- 检查 FFmpeg NVENC 编码支持:通过运行
ffmpeg -encoders | grep nven
命令确认 NVIDIA 硬件编码器是否可用。 - 读取并执行 Manim 脚本:从挂载的
/scripts
目录读取指定的 Manim 脚本(例如manim_a_plus_b.py
),并使用exec
函数执行。
app = modal.App("example-run-local-script", image=image)
@app.function(gpu="A10G")
def run_script():
result = subprocess.run("ffmpeg -encoders | grep nven", shell=True, capture_output=True, text=True)
print(result.stdout)
with open("/scripts/manim_a_plus_b.py", "r", encoding="utf-8") as f:
script_content = f.read()
print(script_content)
exec(script_content, {'__name__': '__main__'})
print("exec finished")
详细说明:
- 使用
@app.function(gpu="A10G")
表明该函数在运行时会分配一块 A10G GPU(24GB 显存),以满足 GPU 加速需求(参考 Modal GPU Docs)。- 通过
subprocess.run
执行 FFmpeg 命令,可以直观查看 NVENC 编码器的输出,验证环境正确配置。- 利用
exec
执行脚本时,传入{'__name__': '__main__'}
保证脚本能按照独立运行时的逻辑执行。
5. 完整代码示例
以下为整合上述各步骤后的完整代码示例:
import subprocess
import modal
image = (
modal.Image.from_registry("nvidia/cuda:12.2.0-devel-ubuntu22.04", add_python="3.10")
.env({"DEBIAN_FRONTEND": "noninteractive", "TZ": "Asia/Shanghai"})
.apt_install("tzdata")
.run_commands("ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' > /etc/timezone")
.apt_install("build-essential", "ffmpeg", "ghostscript", "dvisvgm", "texlive-full")
.apt_install("python3-dev", "pkg-config")
.apt_install("libcairo2-dev", "libpango1.0-dev", "clang")
.run_commands("pip install --upgrade pip setuptools wheel")
.pip_install("numpy", "manim", "latex", "moviepy", "requests")
.pip_install("manimpango")
.add_local_dir("scripts", "/scripts")
)
app = modal.App("example-run-local-script", image=image)
@app.function(gpu="A10G")
def run_script():
result = subprocess.run("ffmpeg -encoders | grep nven", shell=True, capture_output=True, text=True)
print(result.stdout)
with open("/scripts/manim_a_plus_b.py", "r", encoding="utf-8") as f:
script_content = f.read()
print(script_content)
exec(script_content, {'__name__': '__main__'})
print("exec finished")
6. 部署与运行效果
将上述代码保存为 modal_run_with_manim_gpu.py
,并确保你的 Manim 脚本(例如 manim_a_plus_b.py
)存放在本地 scripts
目录中。接着,通过以下命令部署并运行该应用:
modal deploy modal_run_with_manim_gpu.py
modal run modal_run_with_manim_gpu.py::run_script
部署和运行成功后,你会看到类似如下的日志输出:
✓ Initialized. View run at https://modal.com/apps/kaizhao/main/ap-lVLdYTUBaxIlEVugzdYws8
✓ Created objects.
├── 🔨 Created mount E:\code\java\project-litongjava\java-generative-manim\src\main\resources\modal\modal_run_with_manim_gpu.py
├── 🔨 Created mount E:\code\java\project-litongjava\java-generative-manim\src\main\resources\modal\scripts
└── 🔨 Created function run_script.
==========
== CUDA ==
==========
CUDA Version 12.2.0
Container image Copyright (c) 2016-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
This container image and its contents are governed by the NVIDIA Deep Learning Container License.
By pulling and using the container, you accept the terms and conditions of this license:
https://developer.nvidia.com/ngc/nvidia-deep-learning-container-license
A copy of this license is made available in this container at /NGC-DL-CONTAINER-LICENSE for your convenience.
V....D h264_nvenc NVIDIA NVENC H.264 encoder (codec h264)
V..... nvenc NVIDIA NVENC H.264 encoder (codec h264)
V..... nvenc_h264 NVIDIA NVENC H.264 encoder (codec h264)
V..... nvenc_hevc NVIDIA NVENC hevc encoder (codec hevc)
V....D hevc_nvenc NVIDIA NVENC hevc encoder (codec hevc)
上述日志显示:
- Modal 平台成功初始化并创建了相应的挂载目录与函数。
- 容器内的 CUDA 环境信息以及 FFmpeg 对 NVIDIA NVENC 编码器的支持情况均已正确输出,证明环境配置正确,可以利用 GPU 加速进行视频编码和渲染。
总结
通过以上步骤,我们完成了在 Modal 平台上基于 GPU(A10G)运行 Manim 0.18.1 脚本的完整配置工作。整个流程中我们:
- 选取了合适的 CUDA 基础镜像并配置了 Python 环境;
- 安装了构建 ManimPango 和渲染视频所需的系统依赖(编译工具、Pango/Cairo 库、FFmpeg、LaTeX 等);
- 升级了 pip 工具并安装了必要的 Python 包;
- 利用 Modal 的目录挂载功能实现了本地脚本与容器的无缝对接;
- 定义了一个 GPU 函数,检测硬件编码支持并执行 Manim 脚本。
参考了 Modal 官方文档、ManimCommunity/ManimPango 以及 3Blue1Brown 的 Manim 项目说明,这样的配置不仅确保了环境的一致性,还充分利用了 GPU 加速渲染的优势。希望这份文档能帮助你深入理解并顺利部署自己的云端 Manim 渲染应用。