Files
cuframes/tools/spike/common.h
T
gx 604cffb5e5 spike(phase0): minimal CUDA IPC ping-pong producer/consumer
PoC для validation концепта перед инвестированием в Phase 1.

Структура:
- tools/spike/common.h          — типы SharedHeader / SlotDescriptor / NV12 meta
- tools/spike/pingpong_producer.cu — аллоцирует CUDA pool, экспортирует IPC handles
  в /dev/shm/cuframes-spike-<key>, имитирует publish frames с monotonic pattern
- tools/spike/pingpong_consumer.cu — открывает handles, читает frames,
  verify содержимого (no torn frames), измеряет latency, печатает summary
- tools/spike/CMakeLists.txt    — sm_75/86/89/90/120 для RTX 5090
- tools/spike/bench.sh          — basic / multi-consumer / stress scenarios
- tools/spike/README.md         — what / how / acceptance

Намеренные упрощения PoC (не идём в Phase 1 пока без validation):
- 2-slot ring (Phase 1 будет N)
- POSIX shared memory + atomic seq (без Unix socket handshake)
- cudaStreamSynchronize sync (Phase 0 spike проверит будет ли достаточно;
  альтернатива cudaIpcEventHandle_t — отложена)
- NV12 hardcoded (других форматов в Phase 1)
- Drop-oldest backpressure (без ACK protocol)

Acceptance Phase 0:
- p99 latency на RTX 5090 для FullHD < 5 ms
- throughput ≥ 1 GB/s
- multi-consumer (3) с сопоставимой latency
- cross-container работает
- 1-hour stress без VRAM/RAM leak

Если acceptance fail → дизайн пересмотр (sync через CUDA IPC events).
2026-05-14 21:20:39 +01:00

69 lines
2.7 KiB
C++
Raw 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 spike — общие типы / константы для producer и consumer.
//
// NB: реальный protocol будет в libcuframes (Phase 1). Здесь — минимум
// для PoC measurement.
#pragma once
#include <cuda_runtime.h>
#include <cstdint>
#include <cstdio>
#include <cstring>
namespace cuframes_spike {
// Slot — 1 frame в shared VRAM. Producer пишет, consumer читает.
// Используем double-buffering (2 slot'а) — пока consumer читает slot A,
// producer пишет в slot B. Поможет уменьшить contention в PoC.
constexpr int RING_SIZE = 2;
// Format hardcoded для PoC: NV12 (как выдаёт NVDEC по умолчанию).
// Y plane + UV plane (subsampled 2x2).
struct FrameMeta {
int32_t width;
int32_t height;
int32_t pitch_y; // строка Y, выровнен на 256 для CUDA
int32_t pitch_uv; // строка UV
int32_t format; // 0 = NV12
};
// Descriptor одного slot'а. Хранится в /tmp/cuframes-spike-<key>.handle
// — это POSIX shared memory.
struct SlotDescriptor {
cudaIpcMemHandle_t handle; // 64 байта от NVIDIA для IPC
uint64_t producer_seq; // обновляется атомарно при publish
uint64_t consumer_ack_count; // сколько consumers подтвердили
int64_t pts_ns; // timestamp когда producer публикнул
};
// Header shared memory file.
struct SharedHeader {
uint32_t magic; // 0xCC7C1DCC ("CUFRAMES C0")
uint32_t version;
FrameMeta meta;
SlotDescriptor slots[RING_SIZE];
uint64_t global_seq; // монотонная последовательность producer
};
constexpr uint32_t CUFRAMES_SPIKE_MAGIC = 0xCC7C1DCCu;
constexpr uint32_t CUFRAMES_SPIKE_VERSION = 1;
// Helper: error check + abort.
#define CHECK_CUDA(call) do { \
cudaError_t _err = (call); \
if (_err != cudaSuccess) { \
fprintf(stderr, "CUDA error at %s:%d: %s\n", \
__FILE__, __LINE__, cudaGetErrorString(_err)); \
std::exit(1); \
} \
} while (0)
// Получить timestamp в наносекундах (для latency-замеров).
static inline int64_t now_ns() {
timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return static_cast<int64_t>(ts.tv_sec) * 1000000000LL + ts.tv_nsec;
}
} // namespace cuframes_spike