Skip to content

Add an option to disable CUDA constant memory dispatch; add CUPTI-based tests to check that various expected launch types are used - #9542

Open
weinbe2 wants to merge 8 commits into
kokkos:developfrom
weinbe2:feature/constant-memory-dispatch
Open

weinbe2 wants to merge 8 commits into
kokkos:developfrom
weinbe2:feature/constant-memory-dispatch

Conversation

@weinbe2

@weinbe2 weinbe2 commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

This PR includes and supersedes #9352 , as was discussed with @NamjaeChoi .

This PR makes CUDA constant-memory kernel launches configurable through the new KOKKOS_ENABLE_IMPL_CUDA_CONSTANT_MEMORY option, which is enabled by default to preserve existing behavior.

This PR makes it possible to explicitly opt-out of Kokkos allocating constant memory for kernel launches across any/all compilation units. By default, no kernel launches will use constant memory anyway... unless a developer has explicitly opted in to constant memory launches via HintHeavyWeight.

The motivation for this PR is purely "don't allocate what you don't use". If "you" (the developer) know, at compile time, you'll never use HintHeavyWeight launches -> never need constant memory allocated for lambdas/functors... don't bother allocating it. (Put differently, I'm not endorsing the comments on how allocating constant memory can intersects with RDC in the PR this supersedes. I just think the idea in the PR is good on the merits.)

Broad features of this PR:

  • Guards constant-memory resources, initialization, cleanup, kernel declarations, and launch invokers when the option is disabled.
  • Adds constexpr traits representing constant-memory and grid-constant availability, allowing launch routing to handle build configurations without duplicating preprocessor branches.
    • The grid constant trait is technically scope bloat, but it was very in line with other clean-up in this PR, so it seemed like a reasonable expansion of scope.
  • Updates launch-mechanism selection to preserve size-based fallbacks and honor HintLightWeight and HintHeavyWeight consistently across grid-constant configurations.
    • ...and updates the documentation about what configuration is chosen where.
  • Reports the new option in Cuda::print_configuration().

Testing:

Adds a CUPTI-based unit test that observes CUDA runtime calls to verify the selected route:

  • Small functors use kernel arguments.
  • Heavy-weight medium functors use constant memory when enabled, otherwise kernel arguments.
  • Oversized functors use global memory.
  • Host execution produces no CUDA callbacks.

The CMake setup uses CUDA::cupti when available and includes fallback discovery for supported older CMake versions.

The test is relatively coarse grained insofar as it uses functor sizes (64 bytes, 1024 bytes, 33000 bytes) that always trigger kernel argument, (kernel argument/constant memory), global memory independent of grid constant enabled/disabled or with minimal dependence on constant memory availability enabled/disabled.

It could be made more granular---very specific to probing the values in Kokkos_Cuda_Instance.hpp and performing checks against the logic depending on if grid constant is available or constant memory is compiled in... but at some point it all becomes tautological and we're just re-implementing the logic that's already there. In any case, it could be done if requested, just ask.

Related issues / PRs

#9352

Changelog Entry

Unsure if this flag justifies a changelog entry---I guess it could, since opting into this flag when applicable is a (resource) optimization.

Documentation PR

Not yet, but once I've been given a thumbs up on the conventions in this PR I'll submit a PR to kokkos-documentation to update https://github.com/kokkos/kokkos-core-wiki/blob/main/docs/source/API/core/Macros.rst .

NamjaeChoi and others added 8 commits September 15, 2026 07:31
Signed-off-by: Namjae Choi <Namjae.Choi@inl.gov>
Signed-off-by: Evan Weinberg <eweinberg@nvidia.com>
…guments, constant memory, or global memory according to its driver size; sizing was picked to be independent of compile-time constant memory launch support or grid constant usage.

Signed-off-by: Evan Weinberg <eweinberg@nvidia.com>
…a_KernelLaunch.hpp with constexpr logic

Signed-off-by: Evan Weinberg <eweinberg@nvidia.com>
…_Cuda_KernelLaunch.hpp with constexpr logic.

Signed-off-by: Evan Weinberg <eweinberg@nvidia.com>
…ernelLaunch.hpp b/c it has not been updated to reflect grid constant and constant memory launch changes

Signed-off-by: Evan Weinberg <eweinberg@nvidia.com>
Signed-off-by: Evan Weinberg <eweinberg@nvidia.com>
Signed-off-by: Evan Weinberg <eweinberg@nvidia.com>
@weinbe2
weinbe2 force-pushed the feature/constant-memory-dispatch branch from 21a4380 to 0fdcdf3 Compare September 15, 2026 17:17
@NamjaeChoi

Copy link
Copy Markdown
Contributor

Thank you for incorporating my change. I will close my one.

@weinbe2 weinbe2 changed the title Feature/constant memory dispatch Add an option to disable CUDA constant memory dispatch; add CUPTI-based tests to check that various expected launch types are used Sep 15, 2026

@crtrott crtrott left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK we need to talk about this a bit more. I am not sure that introducing an IMPL option makes too much sense. Clearly this is meant for downstream users to use, and we can't come back in the end "oh you have a problem with this, too bad this is just impl stuff".

Also KOKKOS_IMPL_CUDA_USE_GRID_CONSTANT is now unused or? Probably can be removed (that btw seems like a change we could do either way).

@weinbe2

weinbe2 commented Sep 16, 2026

Copy link
Copy Markdown
Contributor Author

OK we need to talk about this a bit more. I am not sure that introducing an IMPL option makes too much sense. Clearly this is meant for downstream users to use, and we can't come back in the end "oh you have a problem with this, too bad this is just impl stuff".

Ah yeah, non-impl makes more sense. I "just" copied that convention from the PR this superseded and didn't think about it too much. I'll change that up tomorrow.


Also KOKKOS_IMPL_CUDA_USE_GRID_CONSTANT is now unused or? Probably can be removed (that btw seems like a change we could do either way).

It's still used here to specify launches with/without __grid_constant__; it's still defined as

#if defined(KOKKOS_COMPILER_NVCC) && !defined(KOKKOS_ARCH_MAXWELL) && \
!defined(KOKKOS_ARCH_PASCAL)
#define KOKKOS_IMPL_CUDA_USE_GRID_CONSTANT
#endif

It's CUDA 11.7+ (so relevant for all CUDA versions supported by Kokkos), but unfortunately it's only Volta+, which is why it needs those details, and why we need 4k vs 32k values flying around, for ex, lower down in Kokkos_Cuda_Instance.hpp. and redundantly in Kokkos_Cuda_KernelLaunch.hpp.


As for where all of the #ifdef KOKKOS_IMPL_USE_GRID_CONSTANT went in that file, it's just wrapped up (for ex) in this diff:

+  static constexpr CudaSpace::size_type KernelArgumentLimit =
#ifdef KOKKOS_IMPL_CUDA_USE_GRID_CONSTANT
-       0x008000; /* 32k bytes */
+  static constexpr bool GridConstantLaunchEnabled = true;
#else
-      0x001000; /*  4k bytes */
+  static constexpr bool GridConstantLaunchEnabled   = false;
#endif
+  static constexpr CudaSpace::size_type KernelArgumentLimit =
+     GridConstantLaunchEnabled ? 0x008000  /* 32k bytes */
+                                : 0x001000; /*  4k bytes */

Disentangling the diff, it becomes:

#ifdef KOKKOS_IMPL_CUDA_USE_GRID_CONSTANT
       0x008000; /* 32k bytes */
#else
      0x001000; /*  4k bytes */
#endif

->

static constexpr CudaSpace::size_type KernelArgumentLimit =
#ifdef KOKKOS_IMPL_CUDA_USE_GRID_CONSTANT
  static constexpr bool GridConstantLaunchEnabled = true;
#else
  static constexpr bool GridConstantLaunchEnabled   = false;
#endif
  static constexpr CudaSpace::size_type KernelArgumentLimit =
     GridConstantLaunchEnabled ? 0x008000  /* 32k bytes */
                                : 0x001000; /*  4k bytes */

Put differently, I created a static constexpr bool GridConstantLaunchEnabled higher up whose value is set to true/false depending on KOKKOS_IMPL_CUDA_USE_GRID_CONSTANT.

Creating GridConstantLaunchEnabled let me take #ifdef nightmares out of the dispatch logic, which is analogous to what I did with KOKKOS_ENABLE_IMPL_CUDA_CONSTANT_MEMORY. It's easy for me to roll this constexpr bool [...] = true/false; design decision back.

@cwpearson cwpearson added the SNL-CI-APPROVAL Required for non-SNL contributions to run on SNL CI label Sep 16, 2026
@maartenarnst

Copy link
Copy Markdown
Contributor

Hey @weinbe2 and @crtrott.

Seeing that this PR proposes adding a test that verifies CUDA API calls, I wanted to bring ReProspect to your attention.

ReProspect is a tool that @romintomasetti and I developed as part of Romin's PhD research, and that we recently published in JOSS. It's a Python package that allows the use of NVIDIA's tools for the analysis of CUDA programs to be scripted end-to-end in a concise Python script, up to programmatic test assertions. It covers CUDA API tracing through Nsight Systems, kernel profiling through Nsight Compute, and binary analysis through the CUDA binary utilities. We have used ReProspect to gain insight into various Kokkos PRs that we have worked on.

In ReProspect's documentation, we have a getting started with CUDA API tracing example that is quite similar in spirit to the test in this PR. In our example, a CUDA program launches 4 kernels with a diamond dependency pattern, and ReProspect is used to verify that the CUDA API calls are as expected. We also have an example that uses ReProspect to trace the CUDA API calls that occur when Kokkos allocates a View.

Looking at the test proposed in this PR, using ReProspect would lead to the test being structured as a pair of a Kokkos source file and a Python analysis script. The Kokkos source file would launch the kernels with the functors of the various sizes. The companion Python script would launch Nsight Systems on the executable, read the collected trace, and submit it to test assertions. The setup would likely involve running the test in a Docker container that provides Nsight Systems, Python, and ReProspect (as easy as pip install reprospect :)).

I am not asking for changes on this PR. But a test that verifies CUDA API behavior is a test of a new type in Kokkos. If interest in tests of this type grows, it may be worth comparing approaches at some point, e.g., comparing using CUPTI as done here with using ReProspect. Happy to discuss!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

SNL-CI-APPROVAL Required for non-SNL contributions to run on SNL CI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants