From 39f259f89332e936122f7e02d6088a1dae3fb628 Mon Sep 17 00:00:00 2001 From: Gabriele Bozzola Date: Tue, 4 Aug 2026 02:38:58 -0700 Subject: [PATCH] Add support for multi-arch CUDA binaries This PR follows MAGMA's example and adds `CUDA_TARGETS`. `CUDA_TARGETS` can be used to bake multiple `CUDA_ARCHs` in a single binary. In particular, like in MAGMA, I build real targets (SASS) for all the architectures as well as a virtual target (PTX) for the last one. This allows architectures that were not in CUDA_ARCH to run by compiling the PTX directly. --- Makefile | 16 ++++++++++++++-- README.md | 6 ++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index d4a44790d5..803b371052 100644 --- a/Makefile +++ b/Makefile @@ -45,6 +45,7 @@ XSMM_DIR ?= ../libxsmm # Often /opt/cuda or /usr/local/cuda, but sometimes present on machines that don't support CUDA CUDA_DIR ?= CUDA_ARCH ?= +CUDA_TARGETS ?= # Often /opt/rocm, but sometimes present on machines that don't support HIP ROCM_DIR ?= @@ -188,7 +189,18 @@ CXXFLAGS ?= $(OPT) $(CXXFLAGS.$(CC_VENDOR)) $(if $(PEDANTIC),$(PEDANTICFLAGS)) FFLAGS ?= $(OPT) $(FFLAGS.$(FC_VENDOR)) LIBCXX ?= -lstdc++ NVCCFLAGS ?= -ccbin $(CXX) -Xcompiler '$(OPT)' -Xcompiler -fPIC -ifneq ($(CUDA_ARCH),) +CUDA_TARGETS_UNKNOWN := $(filter-out sm_%,$(CUDA_TARGETS)) +CUDA_SMS := $(patsubst sm_%,%,$(filter sm_%,$(CUDA_TARGETS))) +CUDA_SMS := $(shell printf "%s\n" $(CUDA_SMS) | sort -n) +cuda_gencode_sm = -gencode arch=compute_$(1),code=sm_$(1) +cuda_gencode_compute = -gencode arch=compute_$(1),code=compute_$(1) +ifneq ($(strip $(CUDA_TARGETS)),) + ifneq ($(strip $(CUDA_TARGETS_UNKNOWN)),) + $(error Unknown CUDA target(s): $(CUDA_TARGETS_UNKNOWN); expected targets such as sm_80) + endif + NVCCFLAGS += $(foreach sm,$(CUDA_SMS),$(call cuda_gencode_sm,$(sm))) \ + $(call cuda_gencode_compute,$(lastword $(CUDA_SMS))) +else ifneq ($(strip $(CUDA_ARCH)),) NVCCFLAGS += -arch=$(CUDA_ARCH) endif HIPCCFLAGS ?= $(filter-out $(OMP_SIMD_FLAG),$(OPT)) -fPIC -munsafe-fp-atomics @@ -1049,7 +1061,7 @@ print-% : CONFIG_VARS = CC CXX FC NVCC NVCC_CXX HIPCC \ OPT CFLAGS CPPFLAGS CXXFLAGS FFLAGS NVCCFLAGS HIPCCFLAGS SYCLFLAGS \ AR ARFLAGS LDFLAGS LDLIBS LIBCXX SED \ - MAGMA_DIR XSMM_DIR CUDA_DIR CUDA_ARCH MFEM_DIR PETSC_DIR NEK5K_DIR ROCM_DIR HIP_ARCH SYCL_DIR + MAGMA_DIR XSMM_DIR CUDA_DIR CUDA_ARCH CUDA_TARGETS MFEM_DIR PETSC_DIR NEK5K_DIR ROCM_DIR HIP_ARCH SYCL_DIR # $(call needs_save,CFLAGS) returns true (a nonempty string) if CFLAGS # was set on the command line or in config.mk (where it will appear as diff --git a/README.md b/README.md index c8aa8f3e26..e669d01b53 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,12 @@ $ make AVX=0 if your compiler does not support gcc-style options, if you are cross compiling, etc. To enable CUDA support, add `CUDA_DIR=/opt/cuda` or an appropriate directory to your `make` invocation. +To target one or more CUDA architectures, pass a space-separated `CUDA_TARGETS` list: + +```console +$ make CUDA_DIR=/opt/cuda CUDA_TARGETS='sm_80 sm_90' +``` + To enable HIP support, add `ROCM_DIR=/opt/rocm` or an appropriate directory. To enable SYCL support, add `SYCL_DIR=/opt/sycl` or an appropriate directory. Note that SYCL backends require building with oneAPI compilers as well: