|
| 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 | + |
0 commit comments