Files
gx 4862247fe2
build / cmake build (CUDA 12.4, Ubuntu 22.04) (push) Successful in 1m46s
build / ffmpeg filter patch (out-of-tree) (push) Failing after 1m30s
v0.4: VMM + POSIX FD — namespace decoupling (no pid share required)
Заменяет cudaMalloc + cudaIpcGetMemHandle на cuMemCreate (VMM) +
cuMemExportToShareableHandle(POSIX_FILE_DESCRIPTOR). FDs передаются consumer'у
через sendmsg(SCM_RIGHTS) в handshake. Frigate (s6-overlay не даёт share PID)
и любой другой consumer работают БЕЗ pid namespace share — только volume mount
unix socket'a /run/cuframes и IPC share для /dev/shm header.

Sync: cudaEventRecord+IPC events → cuStreamSynchronize в do_publish.
Producer ждёт ~1 ms что stream flush'нулся, потом atomic_store(seq).
Consumer читает seq через memory_order_acquire и копирует DtoD без
event wait — HW coherence гарантирована на одном GPU.

ABI break (согласован с user'ом):
  - magic 0xCC7C1DCC → 0xCC7C1DCE (старые consumers fail cleanly)
  - protocol V3 → V4
  - libcuframes.so.0 SOVERSION остаётся, но .so.0.3.0 → .so.0.4.0
  - EXTERNAL ownership убран (VMM требует cuMemCreate-allocated memory,
    нельзя export'нуть произвольный cudaMalloc-pointer как POSIX FD)
  - cuframes-rtsp-source переведён на LIBRARY mode + один D2D memcpy
    в acquire'нутый slot (overhead малый — публишер всё равно делал такой
    D2D из FFmpeg hwframe pool в EXTERNAL pool раньше)

Размер: granularity 2 MB на 5090 → NV12 1920×1080 (~3.1 MB) округляется до
4 MB, +1 MB на slot × 16 × 4 камеры = +64 MB VRAM. Терпимо.

Packet ring (cuframes_packets://) НЕ затронут — отдельный SHM с своим
magic, работает как раньше.

PoC + smoke в spike/:
  - vmm_fd_pingpong/ — minimal cuMemCreate+FD round-trip
  - smoke_v04/ — full publisher+subscriber, 100/100 frames без pid share

Base image: Dockerfile.runtime → CUDA 12.4 (был 13.0). Matching prod
pipeline + Frigate base, иначе libcudart conflict при load.

Compose stack (localhost-infra repo) — параллельный commit:
  - убран pid: container:cuframes-pub-parking из subscribers
  - image теги: gx/cuframes:0.4, gx/cuda-grid-pipeline:phase8,
    gx/frigate:cuframes-v0.4

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-25 20:13:31 +01:00
..

vmm_fd_pingpong — spike для cuframes v0.4

Проверка: можно ли заменить CUDA IPC mem handles на VMM (cuMemCreate)

  • POSIX FD export, чтобы убрать требование shared pid/ipc namespaces между producer и consumer контейнерами.

Результат: работает

Запуск 2 контейнеров без shared pid/ipc, только volume mount для unix-сокета:

producer: granularity=2097152
producer: alloc size=16777216
producer: exported fd=37 for handle
producer: listening on /run/spike/pingpong.sock, awaiting consumer...

consumer: connected to producer
consumer: recv fd=38 size=16777216 magic=0xa7
consumer: imported handle OK
consumer: mapped + access OK
consumer: verify mismatch=0/1048576  → ACK=O
consumer: done (OK)

Ключевые наблюдения

  • Granularity на 5090 = 2 MB. 1920×1080 NV12 (~3.1 MB) округлится до 4 MB. 16 slots × 4 камеры × +1 MB = +64 MB VRAM поверх текущих cuda IPC аллокаций.
  • FD передаётся через sendmsg(SCM_RIGHTS) — kernel прокидывает реальный FD в receiver namespace, переименовывая в свободный номер. Volume mount unix socket'а — единственное требование (/run/cuframes уже монтируется как shared).
  • cuMemImportFromShareableHandle принимает FD как (void *)(uintptr_t)fd.
  • Доступ на consumer side требует cuMemSetAccess с правильным CUmemLocation — device id из своего cuDeviceGet, не наследуется от producer.

Замена events (упрощение этапа C)

CUDA events для IPC не имеют POSIX FD path. Внедрять external semaphores (OPAQUE_FD) — отдельный API, другая sigal/wait семантика. Вместо этого: producer вызывает cuStreamSynchronize(stream) ПЕРЕД atomic_store(seq) в do_publish. Consumer тогда просто читает seq и копирует DtoD — без event wait.

Overhead: ~1 ms на publish × 25 fps = 2.5% CPU time producer'а. Memory coherence гарантирована (один GPU, hardware ensures writes visible после stream sync).

Сборка

docker run --rm -v $PWD:/work -w /work nvidia/cuda:12.4.1-devel-ubuntu22.04 \
    bash -c "apt-get install -y build-essential && make"

Запуск теста

sudo mkdir -p /var/run/spike-pingpong && sudo chmod 777 /var/run/spike-pingpong

docker run -d --name spike-prod --runtime=nvidia --gpus all \
    -v $PWD:/work -v /var/run/spike-pingpong:/run/spike \
    nvidia/cuda:12.4.1-base-ubuntu22.04 /work/producer

docker run --rm --name spike-cons --runtime=nvidia --gpus all \
    -v $PWD:/work -v /var/run/spike-pingpong:/run/spike \
    nvidia/cuda:12.4.1-base-ubuntu22.04 /work/consumer

docker logs spike-prod && docker rm -f spike-prod