From f10413580d47f8cff6a9b0ac15221c7c255bb5e1 Mon Sep 17 00:00:00 2001 From: Evgeny Demchenko Date: Fri, 15 May 2026 06:37:09 +0100 Subject: [PATCH] =?UTF-8?q?docs:=20cross-container=20CUDA=20IPC=20requires?= =?UTF-8?q?=20both=20--ipc=20=D0=B8=20--pid=20namespace=20share?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Реальный тест на 192.168.88.98 (1920x1080 HEVC, 25fps) показал: для отдельных consumer-container'ов недостаточно ipc=container:X — нужен также pid=container:X, иначе cudaIpcOpenEventHandle падает с invalid device context. CUDA driver валидирует IPC peer через /proc//... E2E на реальной камере проверен: publisher (отдельный контейнер) -> consumer (docker exec): 250 frames, 0 gaps publisher (отдельный контейнер) -> consumer (отдельный с pid+ipc): 200, 0 gaps Обновлено: - docs/integration.md compose snippet, verification, troubleshooting section - docker-compose.example.yml — добавлен pid: container:cuframes-cam-test - README.md quickstart — добавлен --pid в docker run subscriber Co-Authored-By: Claude Opus 4.7 --- README.md | 4 +++- docker-compose.example.yml | 5 ++++- docs/integration.md | 34 +++++++++++++++++++++++++++------- 3 files changed, 34 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index aa8facd..56d8a4e 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,9 @@ docker run -d --name cuframes-cam --runtime=nvidia --ipc=shareable \ --rtsp 'rtsp://user:pass@cam/stream' --key cam1 --ring 6 # Subscriber: получает декодированные frames zero-copy -docker run --rm --runtime=nvidia --ipc=container:cuframes-cam \ +# (для cross-container CUDA IPC нужны и --ipc, и --pid — см. docs/integration.md) +docker run --rm --runtime=nvidia \ + --ipc=container:cuframes-cam --pid=container:cuframes-cam \ -v /run/cuframes:/run/cuframes:ro \ gx/cuframes:0.1 \ /usr/local/bin/sub_count --key cam1 --max-frames 100 diff --git a/docker-compose.example.yml b/docker-compose.example.yml index 898612e..d069759 100644 --- a/docker-compose.example.yml +++ b/docker-compose.example.yml @@ -45,8 +45,11 @@ services: environment: NVIDIA_VISIBLE_DEVICES: all NVIDIA_DRIVER_CAPABILITIES: compute,video,utility - # CRITICAL: ipc namespace должен совпадать с publisher'ом + # CRITICAL: обa namespace должны совпадать с publisher'ом — + # ipc нужен для /dev/shm, pid нужен для CUDA driver IPC validation + # (без pid: cudaIpcOpenEventHandle падает с "invalid device context") ipc: "container:cuframes-cam-test" + pid: "container:cuframes-cam-test" volumes: - cuframes_sock:/run/cuframes:ro command: diff --git a/docs/integration.md b/docs/integration.md index 0c830a5..dc76aa3 100644 --- a/docs/integration.md +++ b/docs/integration.md @@ -78,8 +78,9 @@ services: image: gx/cctv-processor:cuda restart: unless-stopped runtime: nvidia - # CRITICAL: --ipc=container:cuframes-cam-parking для shared CUDA context + # CRITICAL: shared IPC + PID namespace с publisher'ом (см. ниже) ipc: container:cuframes-cam-parking + pid: container:cuframes-cam-parking volumes: - cuframes_sock:/run/cuframes:ro environment: @@ -90,9 +91,16 @@ volumes: cuframes_sock: ``` -**Важно**: все consumer'ы должны использовать **тот же** `ipc:` namespace, что -и publisher (через `ipc: container:`). Это нужно для того, -чтобы cudaIpcOpenMemHandle / cudaIpcOpenEventHandle работали корректно. +**Важно — оба флага обязательны** для cross-container CUDA IPC: + +| Флаг | Зачем | +|---|---| +| `ipc: container:` | shared `/dev/shm` (нужен для `shm_open` под header/sockets) | +| `pid: container:` | CUDA driver валидирует IPC peer через `/proc//...`; без этого `cudaIpcOpenEventHandle` падает с `invalid device context` | + +Альтернативы: +- Запускать consumer внутри того же container'а через `docker exec` (наследует все namespaces) — удобно для отладки. +- `--ipc=host --pid=host` — убирает namespacing вообще, но ослабляет изоляцию (не рекомендуется в production). ### Изменения в cctv-processor @@ -198,9 +206,11 @@ Engage с upstream Frigate чтобы добавить custom Source-type ("cufr ls -la /run/cuframes/cam-parking.sock ls -la /dev/shm/cuframes-cam-parking -# 2. Контейнеры в одном IPC namespace -docker inspect cuframes-cam-parking cctv-backend -f '{{.HostConfig.IpcMode}}' -# Должно быть "shareable" для publisher и "container:cuframes-cam-parking" для consumer +# 2. Контейнеры в одном IPC и PID namespace +docker inspect cuframes-cam-parking cctv-backend \ + -f '{{.Name}} ipc={{.HostConfig.IpcMode}} pid={{.HostConfig.PidMode}}' +# Publisher: ipc=shareable pid=(default) +# Consumer: ipc=container:cuframes-cam-parking pid=container:cuframes-cam-parking # 3. Subscriber connect успешен docker exec cctv-backend /usr/local/bin/sub_count --key cam-parking --max-frames 10 @@ -222,6 +232,16 @@ Subscriber не нашёл publisher. Причины: - cuframes_sock:/run/cuframes:ro` в consumer'е - IPC namespace не совпадает — см. checklist пункт 2 +### `cudaIpcOpenEventHandle: invalid device context` +Проявляется в **отдельном** consumer-container'е после успешного handshake (socket +открыт, header валиден, но open event handle не проходит). + +Причина: CUDA driver валидирует sender'а IPC peer'а через `/proc`. Если PID +namespace не совпадает, sender невидим — context считается невалидным. + +Fix: добавить `pid: container:` в consumer's compose service (рядом +с `ipc: container:`). Проверено на CUDA 13.0 + driver 555+. + ### `cudaIpcOpenMemHandle returned 'invalid device pointer'` - Контейнеры в РАЗНЫХ ipc namespace — должны быть в одном (через `ipc: container:` или общий `ipc: shareable`)