Skip to content

Commit 76487b6

Browse files
committed
Add CUPTI always-on profiler
1 parent 7c474f3 commit 76487b6

125 files changed

Lines changed: 7067 additions & 9873 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
._
33
._.*
44
*.pyc
5-
*.so
65
venv*
76
build
87
lib

Dockerfile.cupti

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# syntax=docker/dockerfile:1.7
2+
#
3+
# Build prebuilt CUPTI profiler libraries for a given CUDA version/major.
4+
# Intended to be used with `docker buildx build --platform ... --output type=local,...`.
5+
#
6+
# Example:
7+
# docker buildx build --platform linux/amd64,linux/arm64 \
8+
# --build-arg CUDA_VERSION=12.4.1 --build-arg CUDA_MAJOR=12 \
9+
# -f Dockerfile.cupti --output type=local,dest=dist/cu12 .
10+
#
11+
ARG CUDA_VERSION=12.4.1
12+
FROM --platform=$TARGETPLATFORM nvidia/cuda:${CUDA_VERSION}-devel-ubuntu22.04 AS builder
13+
14+
ARG CUDA_MAJOR=12
15+
ARG TARGETARCH
16+
17+
WORKDIR /src
18+
19+
RUN apt-get update && apt-get install -y --no-install-recommends \
20+
build-essential \
21+
ca-certificates \
22+
git \
23+
make \
24+
&& rm -rf /var/lib/apt/lists/*
25+
26+
# Copy the repo to build context.
27+
COPY . .
28+
29+
# Build the shared library and place it under /out/<arch>-cu<major>/libgscuptiprof.so
30+
#
31+
# Note: CUDA devel images usually ship CUPTI under /usr/local/cuda/extras/CUPTI
32+
# (headers + libs). We point Makefile vars there to avoid distro-dependent packages.
33+
RUN set -eux; \
34+
arch_tag="${TARGETARCH:-}"; \
35+
case "$arch_tag" in \
36+
amd64|arm64) : ;; \
37+
*) echo "Unsupported TARGETARCH: $arch_tag" >&2; exit 2 ;; \
38+
esac; \
39+
make cupti \
40+
CUDA_HOME=/usr/local/cuda \
41+
CUDA_MAJOR="${CUDA_MAJOR}"; \
42+
mkdir -p "/out/${arch_tag}-cu${CUDA_MAJOR}"; \
43+
cp -f "build/libgscuptiprof.so.${CUDA_MAJOR}" "/out/${arch_tag}-cu${CUDA_MAJOR}/libgscuptiprof.so"
44+
45+
FROM scratch AS out
46+
COPY --from=builder /out/ /
47+

MANIFEST.in

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
include README.md
22
include LICENSE
33
include NOTICE
4-
include lib
4+
recursive-include graphsignal/_native *
5+
recursive-include src/cupti *.cpp
6+
include Makefile

Makefile

Lines changed: 267 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,267 @@
1+
SHELL := /usr/bin/env bash
2+
3+
# Build the CUPTI profiler shared library used by `graphsignal.profilers.cupti_profiler`
4+
#
5+
# Requirements:
6+
# - CUDA Toolkit installed (for libcupti.so; usually under CUDA_HOME)
7+
# - CUPTI headers installed (Ubuntu: `apt-get install libcupti-dev`, usually /usr/include/cupti.h)
8+
# - Linux is the intended target (CUPTI is not supported on macOS)
9+
#
10+
# Typical usage:
11+
# make cupti
12+
# make cupti-install
13+
#
14+
# Override CUDA_HOME if needed:
15+
# make cupti CUDA_HOME=/usr/local/cuda-12.3
16+
17+
# ---------------- Platform ----------------
18+
UNAME_S := $(shell uname -s)
19+
UNAME_M := $(shell uname -m)
20+
21+
# ---------------- CUDA / CUPTI ----------------
22+
CUDA_HOME ?= /usr/local/cuda
23+
# CUDA major version used for the build artifacts (e.g. 12, 13).
24+
# You can override explicitly: `make cupti CUDA_MAJOR=13 CUDA_HOME=/usr/local/cuda-13.1`
25+
CUDA_MAJOR ?=
26+
# On Ubuntu, `cupti.h` typically comes from `libcupti-dev` (often installed to /usr/include).
27+
# libcupti.so typically comes from the CUDA Toolkit under CUDA_HOME.
28+
CUDA_TARGET ?= $(if $(filter aarch64 arm64,$(UNAME_M)),sbsa-linux,x86_64-linux)
29+
30+
# Prefer system header from libcupti-dev; fall back to CUDA_HOME.
31+
CUPTI_INCLUDE_DIR ?= $(if $(wildcard /usr/include/cupti.h),/usr/include,$(CUDA_HOME)/targets/$(CUDA_TARGET)/include)
32+
33+
# Default to CUDA_HOME targets layout; pick lib64 if present, otherwise lib.
34+
CUPTI_LIB_DIR ?= $(shell \
35+
if [ -f "$(CUDA_HOME)/targets/$(CUDA_TARGET)/lib64/libcupti.so" ] || [ -f "$(CUDA_HOME)/targets/$(CUDA_TARGET)/lib64/libcupti.so.1" ]; then \
36+
echo "$(CUDA_HOME)/targets/$(CUDA_TARGET)/lib64"; \
37+
else \
38+
echo "$(CUDA_HOME)/targets/$(CUDA_TARGET)/lib"; \
39+
fi \
40+
)
41+
42+
# ---------------- Toolchain ----------------
43+
CXX ?= g++
44+
NVCC ?= nvcc
45+
CXXFLAGS ?= -O2 -fPIC -std=c++17
46+
CPPFLAGS ?= -I$(CUPTI_INCLUDE_DIR)
47+
NVCCFLAGS ?= -O2 -std=c++17 -I$(CUPTI_INCLUDE_DIR) -I$(CUDA_HOME)/include --compiler-options -fPIC
48+
49+
# ---------------- Build outputs ----------------
50+
SRC := src/cupti/cupti_profiler.cpp src/cupti/cupti_activity.cpp src/cupti/event_buckets.cpp src/cupti/debug_print.cpp
51+
BUILD_DIR := build
52+
OUT := $(BUILD_DIR)/libgscuptiprof.so$(if $(CUDA_MAJOR),.$(CUDA_MAJOR),)
53+
54+
# ---------------- Tests ----------------
55+
TEST_SRC := src/test/event_buckets_test.cpp src/cupti/event_buckets.cpp src/cupti/debug_print.cpp
56+
TEST_OUT := $(BUILD_DIR)/event_buckets_test
57+
58+
TEST_CUPTI_TEST_SRC := src/test/cupti_activity_test.cpp
59+
TEST_CUPTI_OUT := $(BUILD_DIR)/cupti_activity_test
60+
TEST_CUPTI_TEST_OBJ := $(BUILD_DIR)/cupti_activity_test.o
61+
TEST_CUPTI_OTHER_OBJ := $(BUILD_DIR)/cupti_activity.o $(BUILD_DIR)/event_buckets.o $(BUILD_DIR)/debug_print.o
62+
TEST_CUPTI_LDFLAGS := --compiler-options -pthread
63+
TEST_CUPTI_LDLIBS := -L$(CUPTI_LIB_DIR) -lcupti -ldl -lcudart
64+
65+
LDFLAGS ?= -shared
66+
LDLIBS ?= -L$(CUPTI_LIB_DIR) -lcupti -ldl -pthread
67+
68+
TEST_LDFLAGS ?=
69+
TEST_LDLIBS ?= -pthread
70+
71+
# ---------------- Packaging ----------------
72+
# Where the .so should live inside the installed Python package
73+
PKG_NATIVE_DIR := graphsignal/_native
74+
PKG_ARCH := $(if $(filter aarch64 arm64,$(UNAME_M)),arm64,amd64)
75+
PKG_OUT_DIR := $(PKG_NATIVE_DIR)/$(PKG_ARCH)-cu$(CUDA_MAJOR)
76+
PKG_OUT := $(PKG_OUT_DIR)/libgscuptiprof.so
77+
78+
# ---------------- Docker buildx (prebuilt artifacts) ----------------
79+
#
80+
# These targets build precompiled Linux libraries for common arch/CUDA majors
81+
# using Docker buildx. No GPU is required to *build*; only to run CUPTI tests.
82+
#
83+
# Output layout:
84+
# dist/cupti/<arch>-cu<major>/libgscuptiprof.so
85+
#
86+
BUILDX_PLATFORMS ?= linux/amd64,linux/arm64
87+
BUILDX_BUILDER ?= graphsignal-builder
88+
BUILDX_OUT_DIR ?= dist/cupti
89+
CUDA12_VERSION ?= 12.4.1
90+
CUDA13_VERSION ?= 13.0.0
91+
92+
.PHONY: all cupti cupti-install test test-event-buckets test-cupti-activity clean distclean info \
93+
buildx-setup cupti-buildx cupti-buildx-cu12 cupti-buildx-cu13 cupti-buildx-install
94+
95+
all: cupti
96+
97+
test: test-event-buckets test-cupti-activity
98+
99+
info:
100+
@echo "UNAME_S=$(UNAME_S)"
101+
@echo "UNAME_M=$(UNAME_M)"
102+
@echo "CUDA_TARGET=$(CUDA_TARGET)"
103+
@echo "CUDA_HOME=$(CUDA_HOME)"
104+
@echo "CUDA_MAJOR=$(CUDA_MAJOR)"
105+
@echo "CUPTI_INCLUDE_DIR=$(CUPTI_INCLUDE_DIR)"
106+
@echo "CUPTI_LIB_DIR=$(CUPTI_LIB_DIR)"
107+
@echo "PKG_ARCH=$(PKG_ARCH)"
108+
@echo "PKG_OUT=$(PKG_OUT)"
109+
@echo "BUILDX_PLATFORMS=$(BUILDX_PLATFORMS)"
110+
@echo "BUILDX_BUILDER=$(BUILDX_BUILDER)"
111+
@echo "BUILDX_OUT_DIR=$(BUILDX_OUT_DIR)"
112+
@echo "CUDA12_VERSION=$(CUDA12_VERSION)"
113+
@echo "CUDA13_VERSION=$(CUDA13_VERSION)"
114+
@echo "CXX=$(CXX)"
115+
@echo "CXXFLAGS=$(CXXFLAGS)"
116+
@echo "CPPFLAGS=$(CPPFLAGS)"
117+
@echo "LDFLAGS=$(LDFLAGS)"
118+
@echo "LDLIBS=$(LDLIBS)"
119+
120+
$(BUILD_DIR):
121+
@mkdir -p "$(BUILD_DIR)"
122+
123+
# ---------------- Build / install ----------------
124+
cupti: $(OUT)
125+
126+
$(OUT): $(SRC) | $(BUILD_DIR)
127+
@if [[ "$(UNAME_S)" == "Darwin" ]]; then \
128+
echo "CUPTI build is not supported on macOS (CUPTI is Linux/Windows only)."; \
129+
exit 1; \
130+
fi
131+
@if [[ -z "$(CUDA_MAJOR)" ]]; then \
132+
echo "Error: CUDA_MAJOR is required (e.g. make cupti CUDA_MAJOR=13 CUDA_HOME=/usr/local/cuda-13.1)"; \
133+
exit 1; \
134+
fi
135+
@echo "Building $@"
136+
$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) -o "$@" $(SRC) $(LDLIBS)
137+
138+
cupti-install: $(OUT)
139+
@if [[ -z "$(CUDA_MAJOR)" ]]; then \
140+
echo "Error: CUDA_MAJOR is required (e.g. make cupti-install CUDA_MAJOR=13 CUDA_HOME=/usr/local/cuda-13.1)"; \
141+
exit 1; \
142+
fi
143+
@mkdir -p "$(PKG_OUT_DIR)"
144+
@cp -f "$(OUT)" "$(PKG_OUT)"
145+
@echo "Installed: $(PKG_OUT)"
146+
@echo "Note: runtime still requires libcupti.so to be discoverable (e.g. set LD_LIBRARY_PATH to $(CUPTI_LIB_DIR))."
147+
148+
# ---------------- Docker buildx ----------------
149+
buildx-setup:
150+
@docker buildx inspect "$(BUILDX_BUILDER)" >/dev/null 2>&1 && docker buildx use "$(BUILDX_BUILDER)" >/dev/null 2>&1 || \
151+
docker buildx create --name "$(BUILDX_BUILDER)" --driver docker-container --use >/dev/null
152+
@docker run --privileged --rm tonistiigi/binfmt --install all
153+
@docker buildx inspect --bootstrap >/dev/null
154+
@echo "buildx is ready"
155+
156+
cupti-buildx: cupti-buildx-cu12 cupti-buildx-cu13
157+
158+
cupti-buildx-cu12:
159+
@mkdir -p "$(BUILDX_OUT_DIR)"
160+
docker buildx build \
161+
--builder "$(BUILDX_BUILDER)" \
162+
--platform "$(BUILDX_PLATFORMS)" \
163+
--build-arg CUDA_VERSION="$(CUDA12_VERSION)" \
164+
--build-arg CUDA_MAJOR=12 \
165+
-f Dockerfile.cupti \
166+
--output type=local,dest="$(BUILDX_OUT_DIR)" \
167+
.
168+
169+
cupti-buildx-cu13:
170+
@mkdir -p "$(BUILDX_OUT_DIR)"
171+
docker buildx build \
172+
--builder "$(BUILDX_BUILDER)" \
173+
--platform "$(BUILDX_PLATFORMS)" \
174+
--build-arg CUDA_VERSION="$(CUDA13_VERSION)" \
175+
--build-arg CUDA_MAJOR=13 \
176+
-f Dockerfile.cupti \
177+
--output type=local,dest="$(BUILDX_OUT_DIR)" \
178+
.
179+
180+
cupti-buildx-install:
181+
@set -euo pipefail; \
182+
shopt -s nullglob; \
183+
# buildx local multi-platform output may be nested under linux_<arch>/...
184+
paths=( \
185+
"$(BUILDX_OUT_DIR)"/*-cu*/libgscuptiprof.so \
186+
"$(BUILDX_OUT_DIR)"/linux_*/*-cu*/libgscuptiprof.so \
187+
); \
188+
real_paths=(); \
189+
for p in "$${paths[@]}"; do \
190+
[[ -f "$$p" ]] && real_paths+=( "$$p" ); \
191+
done; \
192+
paths=( "$${real_paths[@]}" ); \
193+
if (( $${#paths[@]} == 0 )); then \
194+
echo "No buildx artifacts found under $(BUILDX_OUT_DIR)/<arch>-cu<major>/libgscuptiprof.so"; \
195+
echo "Also checked: $(BUILDX_OUT_DIR)/linux_<arch>/<arch>-cu<major>/libgscuptiprof.so"; \
196+
echo "Run: make cupti-buildx (or cupti-buildx-cu12/cu13)"; \
197+
exit 1; \
198+
fi; \
199+
for p in "$${paths[@]}"; do \
200+
d="$$(basename "$$(dirname "$$p")")"; \
201+
mkdir -p "$(PKG_NATIVE_DIR)/$$d"; \
202+
cp -f "$$p" "$(PKG_NATIVE_DIR)/$$d/libgscuptiprof.so"; \
203+
echo "Installed: $(PKG_NATIVE_DIR)/$$d/libgscuptiprof.so"; \
204+
done
205+
206+
# ---------------- Tests ----------------
207+
test-event-buckets: $(TEST_OUT)
208+
@echo "Running test: $(TEST_OUT)"
209+
@./$(TEST_OUT)
210+
211+
$(TEST_OUT): $(TEST_SRC) | $(BUILD_DIR)
212+
@echo "Building test: $@"
213+
$(CXX) $(CXXFLAGS) $(TEST_LDFLAGS) -o "$@" $(TEST_SRC) $(TEST_LDLIBS)
214+
215+
test-cupti-activity:
216+
@bash -e -c '\
217+
if [[ "$(UNAME_S)" == "Darwin" ]]; then \
218+
echo "Skipping cupti_activity test (CUPTI is Linux/Windows only)."; \
219+
exit 0; \
220+
fi; \
221+
if [[ ! -f "$(CUPTI_INCLUDE_DIR)/cupti.h" ]]; then \
222+
echo "Skipping cupti_activity test: cupti.h not found under $(CUPTI_INCLUDE_DIR)"; \
223+
echo "Install headers (Ubuntu: apt-get install libcupti-dev) or set CUPTI_INCLUDE_DIR."; \
224+
exit 0; \
225+
fi; \
226+
if [[ ! -f "$(CUPTI_LIB_DIR)/libcupti.so" && ! -f "$(CUPTI_LIB_DIR)/libcupti.so.1" ]]; then \
227+
echo "Skipping cupti_activity test: libcupti.so not found under $(CUPTI_LIB_DIR)"; \
228+
echo "Install CUDA Toolkit / CUPTI runtime or set CUDA_HOME / CUPTI_LIB_DIR."; \
229+
exit 0; \
230+
fi; \
231+
$(MAKE) $(TEST_CUPTI_OUT); \
232+
echo "Running test: $(TEST_CUPTI_OUT)"; \
233+
./$(TEST_CUPTI_OUT); \
234+
'
235+
236+
$(TEST_CUPTI_OUT): $(TEST_CUPTI_TEST_OBJ) $(TEST_CUPTI_OTHER_OBJ) | $(BUILD_DIR)
237+
@echo "Linking test: $@"
238+
$(NVCC) $(TEST_CUPTI_LDFLAGS) -o "$@" $(TEST_CUPTI_TEST_OBJ) $(TEST_CUPTI_OTHER_OBJ) $(TEST_CUPTI_LDLIBS)
239+
240+
$(TEST_CUPTI_TEST_OBJ): $(TEST_CUPTI_TEST_SRC) | $(BUILD_DIR)
241+
@echo "Compiling test file with nvcc: $@"
242+
$(NVCC) $(NVCCFLAGS) -x cu -c -o "$@" $(TEST_CUPTI_TEST_SRC)
243+
244+
$(BUILD_DIR)/cupti_activity.o: src/cupti/cupti_activity.cpp | $(BUILD_DIR)
245+
@echo "Compiling cupti_activity.cpp with g++: $@"
246+
@if [[ ! -f "$(CUPTI_INCLUDE_DIR)/cupti.h" ]]; then \
247+
echo "Error: cupti.h not found under $(CUPTI_INCLUDE_DIR)"; \
248+
echo "Set CUDA_HOME or CUPTI_INCLUDE_DIR to the correct path."; \
249+
exit 1; \
250+
fi
251+
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c -o "$@" src/cupti/cupti_activity.cpp
252+
253+
$(BUILD_DIR)/event_buckets.o: src/cupti/event_buckets.cpp | $(BUILD_DIR)
254+
@echo "Compiling event_buckets.cpp with g++: $@"
255+
$(CXX) $(CXXFLAGS) -c -o "$@" src/cupti/event_buckets.cpp
256+
257+
$(BUILD_DIR)/debug_print.o: src/cupti/debug_print.cpp | $(BUILD_DIR)
258+
@echo "Compiling debug_print.cpp with g++: $@"
259+
$(CXX) $(CXXFLAGS) -c -o "$@" src/cupti/debug_print.cpp
260+
261+
# ---------------- Clean ----------------
262+
clean:
263+
@rm -rf "$(BUILD_DIR)"
264+
265+
distclean: clean
266+
@rm -f "$(PKG_OUT)"
267+

NOTICE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Graphsignal Tracer
1+
Graphsignal SDK
22
Copyright 2021 Graphsignal, Inc.
33

44
This product includes software developed at Graphsignal (https://graphsignal.com).

0 commit comments

Comments
 (0)