Files
cuframes/docs/benchmarks-phase0.md
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

158 lines
5.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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
```bash
# Сборка 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