docs: cross-container CUDA IPC requires both --ipc и --pid namespace share

Реальный тест на 192.168.88.98 (1920x1080 HEVC, 25fps) показал: для отдельных
consumer-container'ов недостаточно ipc=container:X — нужен также
pid=container:X, иначе cudaIpcOpenEventHandle падает с invalid device
context. CUDA driver валидирует IPC peer через /proc/<pid>/...

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 <noreply@anthropic.com>
This commit is contained in:
2026-05-15 06:37:09 +01:00
parent 44dab75e08
commit f10413580d
3 changed files with 34 additions and 9 deletions
+3 -1
View File
@@ -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
+4 -1
View File
@@ -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:
+27 -7
View File
@@ -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:<publisher_container>`). Это нужно для того,
чтобы cudaIpcOpenMemHandle / cudaIpcOpenEventHandle работали корректно.
**Важно — оба флага обязательны** для cross-container CUDA IPC:
| Флаг | Зачем |
|---|---|
| `ipc: container:<publisher>` | shared `/dev/shm` (нужен для `shm_open` под header/sockets) |
| `pid: container:<publisher>` | CUDA driver валидирует IPC peer через `/proc/<pid>/...`; без этого `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:<publisher>` в consumer's compose service (рядом
с `ipc: container:<publisher>`). Проверено на CUDA 13.0 + driver 555+.
### `cudaIpcOpenMemHandle returned 'invalid device pointer'`
- Контейнеры в РАЗНЫХ ipc namespace — должны быть в одном (через
`ipc: container:<publisher>` или общий `ipc: shareable`)