Skip to main content

GPU Monitoring Client

Project description

GPUFlight Client Library (gpufl)

The Flight Recorder for GPU Production Workloads.

gpufl is a low-overhead, always-on C++ observability library for GPU applications. Built on CUPTI (NVIDIA) and rocprofiler-sdk (AMD), it captures kernel telemetry, SASS-level profiling, and system metrics with under 2% overhead in monitoring mode. Unlike traditional profilers (Nsight) that stop the world with 20-200x slowdown, GPUFlight is designed to run continuously in production — capturing kernel telemetry and logical scopes into structured logs.

Project Status: Beta (Pre-1.0)

GPUFlight is usable today and published to PyPI, but it's pre-1.0 — current releases are 0.1.0.devN dev builds. The public API and the on-the-wire log format may still change between releases; the first stable contract is v1.0.0. Pin an exact version if you depend on it.

To keep the initial design coherent, we are not currently accepting major feature Pull Requests. However, we welcome:

  • Bug reports and local build issues.
  • Documentation improvements and typo fixes.
  • Feature requests and architectural suggestions via GitHub Issues.

Live Demo

Try the portal with real session data — no sign-up required:

https://gpufl-front.vercel.app/demo/gdemo_4R98GA5MzYdosqvNsUqdp_MaUgEcDHABS2C5PHbCDQE

Key Features

  • Kernel Monitoring: Automatically intercepts all CUDA kernel launches via CUPTI.
  • Production Grade: Uses a Lock-Free Ring Buffer and a Background Collector Thread to decouple logging from your hot path.
  • Logical Scoping: Group thousands of micro-kernels into meaningful phases (e.g., "Inference", "PhysicsStep") using GFL_SCOPE or gpufl.Scope.
  • Rich Metadata: Captures kernel names, grid/block dimensions, register counts, shared memory usage, occupancy with per-resource breakdown, and CPU stack traces.
  • Profiling Engines: Choose from PC Sampling (stall analysis), SASS Metrics (instruction-level divergence), or Range Profiler (hardware counters) — one engine per session.
  • System Monitoring: Collects GPU utilization, VRAM, temperature, power, and clock speeds via NVML.
  • Sidecar Ready: Outputs structured NDJSON logs with automatic rotation and gzip compression.
  • Direct Upload: Opt-in remote_upload=True mode POSTs telemetry straight to the GPUFlight backend — ideal for local dev, SSH, and Jupyter workflows where running the sidecar agent is overkill.
  • Vendor Agnostic Design: Architecture ready for AMD (ROCm) support.

Installation

Python (PyPI)

pip install "gpufl[analyzer,viz]"

For full NVML support (GPU utilization/VRAM monitoring), build from source inside a CUDA devel container:

git clone https://github.com/gpu-flight/gpufl-client.git
CMAKE_ARGS="-DBUILD_TESTING=OFF" pip install "./gpufl-client[analyzer,viz]"

C++ (CMake FetchContent)

cmake_minimum_required(VERSION 3.31)
project(my_app LANGUAGES CXX CUDA)

include(FetchContent)
FetchContent_Declare(
    gpufl
    GIT_REPOSITORY https://github.com/gpu-flight/gpufl-client.git
    GIT_TAG        v0.1.0.dev7   # pin a release tag — see the Releases page for the latest
)
FetchContent_MakeAvailable(gpufl)

add_executable(my_app main.cu)
target_link_libraries(my_app PRIVATE gpufl::gpufl CUDA::cudart CUDA::cupti)

Quick Start (Python + Docker)

The recommended way to get started is with a Docker container. See example/python/docker/Dockerfile for a ready-to-use setup with PyTorch and Jupyter Lab.

cd example/python/docker
docker build -t gpufl-python .
docker run --gpus all -p 8888:8888 -v $(pwd)/notebooks:/workspace gpufl-python
import torch
import gpufl

gpufl.init("my-app",
           log_path="./my_logs",
           sampling_auto_start=True,
           enable_kernel_details=True,
           enable_stack_trace=True)

a = torch.randn(1024, 1024, device="cuda")
b = torch.randn(1024, 1024, device="cuda")
c = a @ b
torch.cuda.synchronize()

gpufl.shutdown()

Profiling Engines

CUPTI only allows one profiling mode per CUDA context at a time. Choose an engine at init:

from gpufl import ProfilingEngine

gpufl.init("my-app",
           log_path="./logs",
           profiling_engine=ProfilingEngine.PcSampling,
           enable_kernel_details=True)
Engine What it collects Analyzer method Best for
PcSampling Warp stall reasons (statistical sampling) session.inspect_stalls() Finding why warps are stalling
SassMetrics Per-instruction execution counts (binary instrumentation) session.inspect_profile_samples() Thread divergence detection
RangeProfiler SM throughput, L1/L2 hit rates, DRAM bandwidth, tensor core % session.inspect_perf_metrics() Hardware counter deep-dives
None Kernel metadata only (names, timing, occupancy) session.inspect_hotspots() Production monitoring with minimal overhead

C++ Usage

gpufl::InitOptions opts;
opts.app_name = "my_app";
opts.log_path = "my_logs";
opts.enable_kernel_details = true;
opts.enable_stack_trace = true;
opts.sampling_auto_start = true;
opts.profiling_engine = gpufl::ProfilingEngine::SassMetrics;

gpufl::init(opts);

GFL_SCOPE("training_step") {
    // your CUDA code here
}

gpufl::shutdown();

Talking to the Backend

gpufl can optionally interact with the GPUFlight backend in two independent ways, both opt-in:

Capability Opt in via What happens
Fetch remote named config config_name="..." gpufl.init() does a one-off GET /api/v1/config?config=<name> before monitoring starts and applies the returned fields to your InitOptions.
Direct log upload remote_upload=True A background thread POSTs every NDJSON line to /api/v1/events/<type> in parallel with the on-disk write. Intended for local / SSH / Jupyter workflows.

Both require backend_url + api_key to be set. Setting those two fields alone does nothing — you must opt into at least one of the two capabilities above.

Configuration precedence

When multiple sources set the same field, higher beats lower:

5. The kwargs you pass to gpufl.init()            ← highest
4. Env vars (GPUFL_BACKEND_URL, GPUFL_API_KEY, ...)
3. Local config file (config_file=...)
2. Remote named config (when config_name is set)
1. Built-in defaults                              ← lowest

Quick start

import gpufl

# Just live upload — no remote config fetch
gpufl.init("my_app",
           log_path="./logs",
           backend_url="https://api.gpuflight.com",
           api_key="gpfl_xxxxxxxxxxxx",
           remote_upload=True)

# Just remote config fetch — no upload (production uses the sidecar)
gpufl.init("my_app",
           backend_url="https://api.gpuflight.com",
           api_key="gpfl_xxxxxxxxxxxx",
           config_name="production")

# Both
gpufl.init("my_app",
           backend_url="https://api.gpuflight.com",
           api_key="gpfl_xxxxxxxxxxxx",
           config_name="production",
           remote_upload=True)

Or via environment:

export GPUFL_BACKEND_URL=https://api.gpuflight.com
export GPUFL_API_KEY=gpfl_xxxxxxxxxxxx
export GPUFL_CONFIG_NAME=production     # opt into remote config
export GPUFL_REMOTE_UPLOAD=1            # opt into live upload
python my_training_script.py

Upload mechanics

  • The client writes NDJSON to disk as usual AND POSTs each line in parallel via a dedicated background thread — no added latency on the measurement hot path.
  • Best-effort delivery: 3 retries with exponential backoff per line, then drop. The on-disk NDJSON is still there, so a monitor daemon (or manual re-upload) can always back-fill.
  • An invalid or unauthorized API key disables live upload for the session; the file sink keeps working.

For production workloads with guaranteed delivery, pipe delivery, or cross-process fan-in, keep using the gpufl-monitor sidecar agent — it's the same NDJSON on the wire, just decoupled from the measurement process.


Python Analysis

The gpufl.analyzer module loads NDJSON logs and provides Rich-formatted terminal dashboards.

from gpufl.analyzer import GpuFlightSession

session = GpuFlightSession("./logs", log_prefix="my_logs")

# Executive Summary: session duration, kernel count, GPU utilization, VRAM
session.print_summary()

# Top kernels by GPU time with occupancy breakdown and stack traces
session.inspect_hotspots(top_n=5)

# Time breakdown by user-defined Scope regions
session.inspect_scopes()

# PC Sampling: per-kernel stall reason distribution
session.inspect_stalls(top_n=10)

# SASS Metrics: instruction-level execution counts and divergence
session.inspect_profile_samples(top_n=10)

# Range Profiler: SM throughput, cache hit rates, DRAM bandwidth
session.inspect_perf_metrics(top_n=10)

Analyzer example output

Visualization (Timeline)

The viz module provides interactive matplotlib plots to correlate kernel execution with system metrics.

import gpufl.viz as viz

viz.init("./logs/*.log")
viz.show()

Testing

C++ Tests

The C++ tests use GoogleTest and are hardware-aware — NVIDIA-specific tests skip automatically if no compatible GPU is detected.

cmake --build cmake-build-debug --target gpufl_tests
ctest --test-dir cmake-build-debug --output-on-failure

Python Tests

pip install pytest
pytest tests/python/

Linux Configuration (Required for CUPTI)

To allow non-root users to profile GPU kernels (using CUPTI/PC Sampling) on Linux, you must relax the NVIDIA driver security restrictions. Without this, gpufl may fail to capture kernel activity.

  1. Create a configuration file:

    sudo nano /etc/modprobe.d/nvidia-profiler.conf
    
  2. Add the following line:

    options nvidia NVreg_RestrictProfilingToAdminUsers=0
    
  3. Apply changes and reboot:

    sudo update-initramfs -u
    sudo reboot
    

GPU Flight is open source: github.com/gpu-flight Python package: pypi.org/project/gpufl

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

gpufl-0.1.3.tar.gz (412.1 kB view details)

Uploaded Source

Built Distributions

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

gpufl-0.1.3-cp313-cp313-win_amd64.whl (8.4 MB view details)

Uploaded CPython 3.13Windows x86-64

gpufl-0.1.3-cp313-cp313-manylinux_2_28_x86_64.whl (4.6 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.28+ x86-64

gpufl-0.1.3-cp312-cp312-win_amd64.whl (8.4 MB view details)

Uploaded CPython 3.12Windows x86-64

gpufl-0.1.3-cp312-cp312-manylinux_2_28_x86_64.whl (4.6 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.28+ x86-64

File details

Details for the file gpufl-0.1.3.tar.gz.

File metadata

  • Download URL: gpufl-0.1.3.tar.gz
  • Upload date:
  • Size: 412.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for gpufl-0.1.3.tar.gz
Algorithm Hash digest
SHA256 e55967f67baa26c31b4cf4be756581060639aa7719bb9315e8d519d4cd378d57
MD5 c2b4badbeaad9e4b343a3faaa188f65c
BLAKE2b-256 bc4151a5312a72aaa1a08a24f31d75b0f7c9a51242e6778cf0f9635f4c9a6681

See more details on using hashes here.

File details

Details for the file gpufl-0.1.3-cp313-cp313-win_amd64.whl.

File metadata

  • Download URL: gpufl-0.1.3-cp313-cp313-win_amd64.whl
  • Upload date:
  • Size: 8.4 MB
  • Tags: CPython 3.13, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for gpufl-0.1.3-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 c2aaccc7e78e56c69e70ed888d2edf01ec5d80d0f7e950613dc25fe439d2d0fd
MD5 6dd8192aa3bbccd78698318324d0b671
BLAKE2b-256 7f549d5e0956ec5e079114dcb773c9f53e340330daa11b6feea6bef00026ee28

See more details on using hashes here.

File details

Details for the file gpufl-0.1.3-cp313-cp313-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for gpufl-0.1.3-cp313-cp313-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 79bf32c7e3e4969ac5085480d8efe5b3f037da2483f382aa89312f003d88b63c
MD5 6b5e4573a482090e467947776a903759
BLAKE2b-256 7eb1a9aded389588bd0a1f851a618948d73d98e2aa2edd10cccaea91d554a986

See more details on using hashes here.

File details

Details for the file gpufl-0.1.3-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: gpufl-0.1.3-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 8.4 MB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for gpufl-0.1.3-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 988433a2602f00450d919509e612e15ec86070653ca7648994438b792143e699
MD5 ecb98bb0bed251f2c0a39d28225a80bd
BLAKE2b-256 f9033cf569bf883add6971cbacd07977fb2bdc370ddf2b0730f0458c95f38199

See more details on using hashes here.

File details

Details for the file gpufl-0.1.3-cp312-cp312-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for gpufl-0.1.3-cp312-cp312-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 3fe5b61a66595ab3d677d0e21fb1e7bc1ee2e15df584b113c0a13346dad31f25
MD5 3b3d0072821a9ccd82d5581e23f4fac0
BLAKE2b-256 2808698278ffdf29634a0ddd19eab81bc760bf4681dfc10f389951fe661cc83e

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