Skip to main content

Get the most out of your CPUs and GPUs without leaving Python: streaming multiprocessing pipelines

Project description

gpupipe

Get the most out of your CPUs and GPUs without leaving Python: streaming pipelines of multi-worker stages — parallel downloads feeding GPU inference feeding DB writes — with backpressure, batching, and graceful shutdown handled for you.

Installation

# With uv
uv add git+https://github.com/mogwai/gpupipe.git

# Or pip
pip install git+https://github.com/mogwai/gpupipe.git

The distribution is gpupipe; the module you import is pipe (sklearn-style):

from pipe import Pipe

Quick Start

from pipe import Pipe

class Generator:
    def __call__(self):
        # Generator pattern - yield items, exhaustion signals completion
        for i in range(100):
            yield {"id": i}

class Worker:
    def load(self):
        # Called after process spawn - initialize heavy resources here
        pass

    def __call__(self, item):
        item["processed"] = True
        return item

pipe = Pipe()
pipe.add(Generator(), outqn=20)
pipe.add(Worker(), workers=4, outqn=20)

for result in pipe:
    print(result)

Autoscaling (queue-pressure-based worker scaling) is a planned feature — designed and implemented, but not currently wired into Pipe. See PLANNED.md for the design and re-integration steps.

Capability Tour

GPU pools

pipe.add(GPUWorker(), pergpu=True, outqn=None)      # one worker per GPU
pipe.add(GPUWorker(), gpus=[5, 6], workers=2)       # 2 workers on each of GPUs 5,6
pipe.add(GPUWorker(), gpu_id=0)                     # pin every worker to GPU 0

Each process worker is isolated to its GPU via CUDA_VISIBLE_DEVICES; requesting a GPU that doesn't exist fails loudly instead of silently running on CPU.

CPU affinity

# 16 cores chunked across 4 workers (4 dedicated cores each), BLAS threads sized to match
pipe.add(MelSpectrogram(), workers=4, cpus=range(16))
pipe.add(HeavyCPU(), workers=2, cpu_threads=8)      # just lift the 2-thread BLAS cap

Threaded workers (I/O-bound)

pipe.add(IOWorker(), workers=8, thread=True, outqn=20)   # one process, 8 threads

Streaming async IO (downloads)

from pipe import AsyncPoolWorker

class Downloader(AsyncPoolWorker):
    async def process(self, item):                  # N in flight continuously,
        item["data"] = await fetch(item["url"])     # each result emitted the
        return item                                 # moment it lands - no batch barrier

pipe.add(Downloader(max_concurrent=256), workers=1, outqn=200)

Framework batching

class GPUInference:
    def __call__(self, batch):                      # batch = list of up to 16 items,
        return run_model(batch)                     # partial batches included

pipe.add(GPUInference(), pergpu=True, batch=16)

Send items back for retry: push()

class QualityGate:
    def __call__(self, item):
        if ok(item):
            return item
        if item.setdefault("tries", 0) < 2:
            item["tries"] += 1
            self.push("Renderer", item, timeout=5)  # back to the Renderer stage
            return None
        return item                                 # give up, pass through

One pipeline feeding N DDP ranks

pipe = Pipe(expected_consumers=world_size)          # rank 0 runs the pipe
pipe.start()
# every rank:
for batch in PipeIterator(shared_queue):            # items distributed across ranks,
    train_step(batch)                               # each rank gets its own End

Live stats without log clobbering

pipe = Pipe(stats_interval=3)                       # pinned one-line display on a TTY
pipe.print("checkpoint saved")                      # prints ABOVE the stats line

Profiling

pipe = Pipe(profile=True)   # per-worker cProfile + peak RSS, summary on stop

Testing

# Run all tests
pytest tests/

# Run a specific test
pytest tests/test_basic.py -v

Key Classes

  • Pipe - Main pipeline orchestrator
  • End - Sentinel a root worker returns to signal completion
  • AsyncPoolWorker - Streaming async IO stage: subclass, implement async def process(item)
  • Batcher - Batch items together
  • BufferAndShuffle - Buffer and shuffle items
  • PipeIterator - Read a pipe's output queue from another process (DDP shared mode)

Features

  • Multi-worker stages connected by queues, with backpressure
  • Threaded workers (thread=True) for I/O-bound stages
  • Streaming async IO stages (AsyncPoolWorker: N requests in flight, no batch barrier)
  • Framework batching (batch=N: worker receives a list, partial batches included)
  • GPU pools: pergpu=True, gpu_id=N, or explicit gpus=[...] with per-worker isolation
  • CPU affinity: cpus=[...] chunked across workers, cpu_threads= for BLAS sizing
  • Chunked queue transport (chunk=/chunk_ms=) for small-item edges
  • worker.push(stage, item) - send an item back to an earlier stage (retry/quality gates)
  • DDP shared mode: one pipeline feeds N training ranks (expected_consumers + PipeIterator)
  • Live stats: pinned one-line display on a TTY (pipe.print()/print_above() write above it), rich mode, or poll get_stats() externally
  • Health monitoring with worker restart; graceful shutdown with flush semantics
  • Per-worker profiling (profile=True: cProfile + peak RSS summary)
  • Sequential mode (sequential=True) for single-process debugging
  • HTTP serving (pipe.web) for cross-machine pipelines

Documentation

  • PIPE_REFERENCE.md - the full reference: worker types, return-value semantics, completion signaling, tensor handling, DDP, env vars, pitfalls
  • docs/examples/ - runnable examples and job templates
  • PLANNED.md - designed-but-unwired features (autoscaling)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

gpupipe-0.1.0.tar.gz (113.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

gpupipe-0.1.0-py3-none-any.whl (46.3 kB view details)

Uploaded Python 3

File details

Details for the file gpupipe-0.1.0.tar.gz.

File metadata

  • Download URL: gpupipe-0.1.0.tar.gz
  • Upload date:
  • Size: 113.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.24 {"installer":{"name":"uv","version":"0.9.24","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"KDE neon","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for gpupipe-0.1.0.tar.gz
Algorithm Hash digest
SHA256 6b86478b4a0f4c6053e3475ad88ef737cb04298e9ad3f150887c59c15f03d10b
MD5 3b8a3c70779eeb59740b7c33620ede6d
BLAKE2b-256 6a7632dfdbbbd729f9141fa54c42b78a4a39151f0bbca9a3c82ea9c7e5565e84

See more details on using hashes here.

File details

Details for the file gpupipe-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: gpupipe-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 46.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.24 {"installer":{"name":"uv","version":"0.9.24","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"KDE neon","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for gpupipe-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 af1468ac5ea9272e968063bc0672df8e6c9ebcf4c751ec31051ed4676919488c
MD5 e1a6addaae6d4cd57eea4cc5668b4398
BLAKE2b-256 9d7cba8ce2ed27bb2c55caf2eab1dd3bc932a9a90e05f5fa33754591d7c84b83

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page