Zero-Host-Copy Inference: Keeping the CPU Out of the Hot Path in a C++/CUDA Pipeline (165 FPS) A developer published a bare-metal C++/CUDA video inference pipeline, ZeroHostCopyInference, on GitHub that sustains 165 FPS by keeping frames entirely in GPU memory and eliminating all runtime calls to cudaMalloc, cudaFree, new and delete from the hot path. The InferencePipeline class splits work across three asynchronous worker threads — Source, Detector and Sink — connected by a bounded SafeQueue built on std::mutex and std::condition_variable that applies backpressure by blocking the Source thread when the queue is full, preventing out-of-memory crashes when a decoder pushing 300 FPS outpaces a 165 FPS inference engine. The author chose the custom implementation over NVIDIA DeepStream to avoid GStreamer dependencies and gain full control over the threading model. When modern INT8-quantized neural networks execute in single-digit milliseconds, the system bottleneck shifts from raw compute to I/O and pipeline infrastructure. On discrete GPUs, constantly bouncing high-resolution video frames and intermediate payloads like bounding box tensors across the PCIe bus severely bottlenecks overall throughput. In a Zero-Host-Copy architecture, the data life cycle stays strictly on the GPU. From the initial pre-decode disk read to the final post-encode disk write, frames reside exclusively in device memory, heavily minimizing H2D Host-to-Device and D2H transfers. Furthermore, a strict Zero-Copy pipeline passes payloads between stages strictly via pointers, completely eliminating deep copies. However, redundant PCIe transfers aren’t the only silent performance killers; dynamic memory allocation during runtime is just as fatal. Calling cudaMalloc triggers implicit synchronization, blocking the host CPU on the GPU and wrecking pipeline asynchrony. To max out throughput, a high-performance system requires a strict three-phase life cycle: init, warm-up, and the hot path. During initialization, the application pre-allocates all memory pools, buffers, and queues to their target depths. The warm-up phase then pushes a full processing queue, triggering any lazy allocations or buffer expansions needed for real-world workloads. Once the pipeline drops into the hot path after flushing a few initial frames, dynamic allocation must hit absolute zero. This architecture strictly forbids runtime calls to cudaMalloc or new, relying entirely on recycled memory blocks to guarantee a flat, stable frame rate. Why didn’t I choose NVIDIA DeepStream? DeepStream is great, but building custom GStreamer plugins in C++ is notoriously heavy/inflexible. I wanted to implement a bare-metal pipeline with zero overhead, full control over the threading model, and no GStreamer dependencies to maximize performance and portability. You can view the full bare-metal pipeline implementation on GitHub here: ZeroHostCopyInference https://github.com/Igkho/ZeroHostCopyInference Fast individual components aren’t enough for a high-performance video pipeline. If the hardware decoder pushes 300 FPS but the inference engine pulls 165 FPS, a naive pipeline will OOM Out-Of-Memory and crash the system. To throttle the data flow and prevent memory exhaustion, I designed the InferencePipeline class. It splits the workload across three asynchronous worker threads—Source, Detector, and Sink—operating as a chained producer-consumer: To safely bridge these stages, I built a custom SafeQueue backed by std::mutex and std::condition variable. Standard thread-safe queues typically grow unbounded. To guarantee system stability, my queue enforces strict backpressure by hard-capping the queue depth. If the Detector lags behind the Source, the bounded queue fills up and blocks the Source until slots free up. The OS suspends the Source thread entirely, preventing CPU busy-waiting spin-locking , unbounded queue growth, and memory exhaustion. template