通过两个实验理解 GPU 虚拟化的核心机制:
15 分钟
对应 PPT 第 12 页 + 第 33 页 [动手 1]
// mymalloc.c
#define _GNU_SOURCE
#include <stdio.h>
#include <dlfcn.h>
static size_t total_allocated = 0;
void *malloc(size_t size) {
static void *(*real_malloc)(size_t) = NULL;
if (!real_malloc)
real_malloc = dlsym(RTLD_NEXT, "malloc");
void *p = real_malloc(size);
total_allocated += size;
printf("[HOOK] malloc(%zu) = %p (累计: %zu bytes)\n",
size, p, total_allocated);
return p;
}
# 编译为共享库
gcc -shared -fPIC mymalloc.c -o libmymalloc.so -ldl
# 用 LD_PRELOAD 运行任意程序
LD_PRELOAD=./libmymalloc.so ls -la
# 再试一个
LD_PRELOAD=./libmymalloc.so python3 -c "x = [1]*1000"
ls 和 python3 的 malloc 调用全部被我们的 hook 拦截了malloc 换成 cuMemAlloc,我们就可以:
CUDA_ERROR_OUT_OF_MEMORY关键理解: HAMi 的
libvgpu.so就是用同样的方式 hookcuMemAlloc、cuLaunchKernel等 CUDA API。
对应 PPT 第 34 页 [动手 2]
# 在容器内查看 GPU
docker run --rm --gpus all nvidia/cuda:12.8.0-base-ubuntu22.04 nvidia-smi
# 查看容器内的 GPU 设备文件
docker run --rm --gpus all nvidia/cuda:12.8.0-base-ubuntu22.04 ls -la /dev/nvidia*
# 查看注入的环境变量
docker run --rm --gpus all nvidia/cuda:12.8.0-base-ubuntu22.04 env | grep NVIDIA
# 用 devel 镜像编译并运行 CUDA 程序
docker run --rm --gpus all -v $(pwd):/workspace nvidia/cuda:12.8.0-devel-ubuntu22.04 bash -c "
cd /workspace
cat > test.cu << 'EOF'
#include <stdio.h>
__global__ void hello() {
printf(\"GPU thread %d\\n\", threadIdx.x);
}
int main() {
hello<<<1,4>>>();
cudaDeviceSynchronize();
return 0;
}
EOF
nvcc -o test test.cu && ./test
"
# 编写最简单的 vLLM Dockerfile
cat > Dockerfile << 'EOF'
FROM nvidia/cuda:12.8.0-runtime-ubuntu22.04
RUN apt-get update && apt-get install -y python3-pip && pip install vllm
ENTRYPOINT ["python3", "-m", "vllm.entrypoints.openai.api_server"]
CMD ["--model", "Qwen/Qwen2.5-0.5B-Instruct", "--host", "0.0.0.0", "--port", "8000"]
EOF
# 构建 (可以只做前几步,不一定跑完)
docker build -t vllm-demo:v1 .
# 查看镜像大小和层
docker history vllm-demo:v1
dlsym(RTLD_NEXT, "malloc") 获取原始函数 → 我们的 hook 调用原始函数 → 在前后加入检查逻辑dlsym(RTLD_NEXT, "cuMemAlloc") → 检查显存配额 → 调用真正的 cuMemAllocnvidia-container-runtime-hook 在容器启动前执行mknod 创建设备文件 → mount --bind 挂载驱动库nvidia/cuda:12.8.0-base → ~100MB (只有运行时库)nvidia/cuda:12.8.0-runtime → ~600MB (+cuBLAS/cuFFT)nvidia/cuda:12.8.0-devel → ~3GB (+nvcc+头文件)