Files
cuframes/docs/benchmarks-phase0.md
T
gx c2c2a9751a phase0: benchmark results — PASSED on RTX 5090 (Blackwell sm_120)
Basic (1 producer × 1 consumer):
  p50=75µs  p95=146µs  p99=152µs   (target was <5ms — мы 33× ниже)
  500 frames, 0 torn, 0 skipped, zero-copy verified

Multi-consumer (1 × 3):
  p99 для всех 3: 151-152µs (identical = proof zero-copy без contention)
  300 frames each, 0 torn, 0 skipped

Acceptance criteria — GREEN. Переходим к Phase 1 (libcuframes API).

Sync через cudaStreamSynchronize достаточен для v0.1; CUDA IPC event
handles overlap отложен до v0.2.

Raw measurement logs сохранены в docs/measurements/phase0-consumer-*.log
для verification (4 файла из 2 scenarios).

Также fixed unused variable warning в pingpong_consumer.cu.
2026-05-14 22:02:49 +01:00

5.5 KiB
Raw Blame History

Phase 0 — Benchmark results

CUDA IPC ping-pong measurements. Validates что концепт работает и обеспечивает достаточную производительность перед инвестированием в полную реализацию (Phase 1+).

Raw output каждого run сохранён в docs/measurements/*.log — все числа ниже взяты оттуда.

Hardware

  • GPU: NVIDIA RTX 5090 (Blackwell, sm_120, 32 GB VRAM)
  • Driver: 595.58.03
  • CUDA Toolkit: 13.0.88 (внутри dev-container)
  • Host OS: Ubuntu 24.04 (host) / Ubuntu 24.04 (container)
  • Docker: 29.1.3, nvidia-container-runtime

Methodology

  • Producer аллоцирует 2 CUDA-буфера (NV12 FullHD, 1920×1080 = 3.1 MB/frame), экспортирует cudaIpcMemHandle_t, заполняет Y-plane monotonic pattern (seq % 256), публикует с целевым FPS
  • Consumer открывает handles, читает frames через cudaIpcOpenMemHandle, верифицирует содержимое первой строки Y-plane (no torn frames check), замеряет wall-clock latency producer→consumer

Запуск в одном Docker-контейнере (cuframes-dev), ipc: shareable, shm_size: 2gb. Источник: tools/spike/.

Scenario 1 — Basic (1 producer × 1 consumer)

Raw: docs/measurements/phase0-consumer-basic.log

producer: --fps 30 --duration 30
consumer: --count 500
Metric Value
Frames received 500
Duration 16.63 s
Effective fps 30.06
Frames skipped (producer ahead) 0
Torn frames (data corruption) 0
Zero-copy verified
Latency mean 79 µs
Latency p50 75 µs
Latency p95 146 µs
Latency p99 152 µs
Latency max 2273 µs (cold-start outlier)

Scenario 2 — Multi-consumer (1 producer × 3 consumers)

Raw: docs/measurements/phase0-consumer-multi-c{1,2,3}.log

producer: --fps 30 --duration 60
3× consumer (параллельно): --count 300
Metric C1 C2 C3
Frames received 300 300 300
Effective fps 30.17 30.16 30.16
Frames skipped 0 0 0
Torn frames 0 0 0
Latency mean 152 µs 139 µs 146 µs
Latency p50 80 µs 72 µs 73 µs
Latency p95 145 µs 144 µs 144 µs
Latency p99 152 µs 151 µs 152 µs
Latency max 22.3 ms 19.6 ms 21.2 ms (cold-start)

Key findings:

  • Latency p99 одинаковая для всех 3 consumers (151-152 µs) — proof что zero-copy реально работает (нет contention, нет per-consumer overhead)
  • Все consumers получили все свои 300 frames без skip
  • Zero corruption — cudaStreamSynchronize на producer-стороне достаточен для consistency

Acceptance criteria — RESULT

Criterion Target Actual Status
p99 latency < 5 ms 152 µs (0.15 ms) 33× ниже target
Multi-consumer scalability без degradation identical p99 для всех 3
Torn frames 0 0
Frame skip 0 0
Memory leak (short run) 0 not measured Phase 0.5

Что осталось из Phase 0 (отложено в Phase 1 tests)

  • Cross-container test: producer в одном docker container, consumer в другом, через ipc:container:<name>. Validates production scenario.
  • 1-hour stress run, мониторинг VRAM/RSS на leak
  • CUDA IPC events sync — попробовать cudaIpcEventHandle_t вместо cudaStreamSynchronize для overlap producer-decode и consumer-read

Эти scenarios менее критичны (basic дизайн validated) — переносим в Phase 1, где будут реальные libcuframes API tests.

Решение по design

CUDA IPC sync через cudaStreamSynchronize достаточен для v0.1. Latency 75-152 µs (p50-p99) — well under target 5 ms. Усложнять API event-handles на этом этапе не нужно.

Готовность к Phase 1

GREEN — продолжаем по плану из docs/architecture.md §5.

Phase 1 цели:

  • libcuframes producer/consumer C API
  • Wire-protocol (Unix socket handshake)
  • N-slot ring buffer (вместо 2)
  • ACK protocol для proper backpressure
  • Unit tests + stress (24h leak detection)

Reproduction

# Сборка dev-контейнера (одноразово)
docker compose -f docker/docker-compose.dev.yml up -d --build

# Сборка spike
docker exec cuframes-dev bash -c "
  cd /workspace
  cmake -B build -S tools/spike -G Ninja
  cmake --build build
"

# Basic
docker exec cuframes-dev bash -c "
  cd /workspace
  ./build/pingpong_producer --key smoke --fps 30 --duration 30 &
  sleep 1
  ./build/pingpong_consumer --key smoke --count 500
"

# Multi-consumer
docker exec cuframes-dev bash -c "
  cd /workspace
  ./build/pingpong_producer --key multi --fps 30 --duration 60 &
  sleep 1
  ./build/pingpong_consumer --key multi --count 300 > /tmp/c1.log 2>&1 &
  ./build/pingpong_consumer --key multi --count 300 > /tmp/c2.log 2>&1 &
  ./build/pingpong_consumer --key multi --count 300
  wait
"

Артефакты

  • Source: tools/spike/ (commit 604cffb)
  • Container: cuframes-dev:latest 9 GB (commit 6962bc3)
  • Raw measurement logs: docs/measurements/phase0-consumer-*.log
  • Generated 2026-05-14