Skip to content
/ airelien.dev
Go back
Aurélien AMSELLEM

Lucebox sur Olares One — Épisode 2 : 2h de compile CUDA pour 11 undefined references

Premier build Docker. 2h13 de compile CUDA pour sm_120, et au moment du link, ld vous balance 11 undefined references vers cuMemCreate, cuMemMap, cuMemAddressReserve. Pourquoi ? Parce que libcuda.so.1 n'est pas là où il devrait être.

Si vous avez raté l’épisode 1, je vous remets dans le bain : on essaie de packager Lucebox DFlash en image Docker pour Olares One (RTX 5090 Mobile, sm_120 Blackwell consumer). Personne ne l’a jamais fait. Et là, on lance le premier docker buildx build.

Spoiler épisode 2 : on s’en va déjà se planter au link.

Le Dockerfile naïf

Trois étapes simples dans le builder :

FROM nvidia/cuda:13.0.0-devel-ubuntu22.04 AS builder

RUN apt-get update && apt-get install -y --no-install-recommends \
    git build-essential cmake ninja-build pkg-config \
    libcurl4-openssl-dev ca-certificates python3-pip python3-dev

WORKDIR /src
RUN git clone --depth 1 --recurse-submodules \
    https://github.com/Luce-Org/lucebox-hub /src/lucebox

WORKDIR /src/lucebox/dflash
RUN cmake -B build -S . \
    -DCMAKE_BUILD_TYPE=Release \
    -DGGML_CUDA=ON \
    -DCMAKE_CUDA_ARCHITECTURES="86;89;120" \
    && cmake --build build --target test_dflash -j $(nproc)

Trois architectures CUDA visées : Ampere (86, RTX 3090), Ada (89, RTX 4090), Blackwell consumer (120, RTX 5090). Lucebox auto-détecte sm_120 et le rewrite en 120a au moment du config — bon signe.

Je lance le build. docker buildx build --platform linux/amd64 -t aamsellem/lucebox-qwen36-blackwell:1.0.0 .

Et puis j’attends.

2h13 plus tard

Le compile CUDA pour 3 architectures, sur 16 vCPU dans la VM OrbStack, c’est long. Très long. Les fattn-mma-f16-instance-*.cu.o (Flash Attention multi-head, template instances) prennent 30 à 90 secondes pièce. Et y en a des dizaines. Plus les mmq-instance-* (matmul quantized). Plus template-instances/fattn-vec-instance-*. Plus…

À 7208 secondes (2h00), je suis à [90%]. À 8126 secondes, [98%] Linking CXX static library libdflash27b.a. À 8202 secondes, [100%] Linking CXX executable test_dflash. Yes !

Et boom :

/usr/bin/ld: warning: libcuda.so.1, needed by deps/llama.cpp/ggml/src/ggml-cuda/libggml-cuda.so.0.9.11, not found (try using -rpath or -rpath-link)
/usr/bin/ld: libggml-cuda.so.0.9.11: undefined reference to `cuMemCreate'
/usr/bin/ld: libggml-cuda.so.0.9.11: undefined reference to `cuMemAddressReserve'
/usr/bin/ld: libggml-cuda.so.0.9.11: undefined reference to `cuMemUnmap'
/usr/bin/ld: libggml-cuda.so.0.9.11: undefined reference to `cuMemSetAccess'
/usr/bin/ld: libggml-cuda.so.0.9.11: undefined reference to `cuDeviceGet'
/usr/bin/ld: libggml-cuda.so.0.9.11: undefined reference to `cuMemAddressFree'
/usr/bin/ld: libggml-cuda.so.0.9.11: undefined reference to `cuGetErrorString'
/usr/bin/ld: libggml-cuda.so.0.9.11: undefined reference to `cuDeviceGetAttribute'
/usr/bin/ld: libggml-cuda.so.0.9.11: undefined reference to `cuMemMap'
/usr/bin/ld: libggml-cuda.so.0.9.11: undefined reference to `cuMemRelease'
/usr/bin/ld: libggml-cuda.so.0.9.11: undefined reference to `cuMemGetAllocationGranularity'
collect2: error: ld returned 1 exit status

Onze undefined references. Toutes des fonctions CUDA Driver API VMM (Virtual Memory Management). Le compile a marché, le link rate.

Aïe.

Pourquoi

Sur une machine NVIDIA classique, libcuda.so.1 est fourni par le driver (pas le toolkit CUDA). Il vit dans /usr/lib/x86_64-linux-gnu/libcuda.so.1 et est installé par le pilote NVIDIA, pas par les paquets CUDA.

Dans un container Docker, le driver vient du host via NVIDIA Container Toolkit, au runtime. Au moment du build, dans une image nvidia/cuda:13.0.0-devel, le driver n’est pas là.

Mais NVIDIA a prévu le coup : ils livrent un stub dans /usr/local/cuda/lib64/stubs/libcuda.so. C’est une lib vide qui exporte tous les symboles CUDA Driver API mais sans logique. Au build, ld résout les symboles contre le stub. Au runtime, le vrai libcuda.so.1 du host est utilisé.

Sauf que le stub s’appelle libcuda.so, pas libcuda.so.1. Et libggml-cuda.so cherche le .1. Du coup ld ne le trouve pas, et balance les undefined references.

Le fix qui m’a paru évident

Deux lignes dans le Dockerfile :

ENV LIBRARY_PATH="/usr/local/cuda/lib64/stubs:${LIBRARY_PATH}"
RUN ln -sf /usr/local/cuda/lib64/stubs/libcuda.so \
           /usr/local/cuda/lib64/stubs/libcuda.so.1

Symlink + ajout du path stubs dans LIBRARY_PATH. Logique. Je relance.

2 heures de compile plus tard…

Suite à l’épisode 3, parce que LIBRARY_PATH ne fait pas ce que je croyais.

À très vite !


Disclosure — Tous les benchmarks de ce post tournent sur mon propre Olares One. Si le contenu vous a été utile et que vous envisagez d’en acheter un, commander via ce lien de parrainage vous donne 400 $ de réduction (3 599 $ au lieu de 3 999 $) et me rapporte 200 $. Je le mentionne par transparence — et oui, accessoirement, ça aide à faire vivre le blog (hébergement, domaine, et le temps que je passe à écrire ici). Lien valable jusqu’à fin juin 2026 environ.

Share this post on:

Commentaires