Skip to content

GPU device calls across modules cause local-memory overhead #2094

Open

Description

@AppleChen17

Problem it solves

With NVHPC 26.3, GPU routines defined in separate source files are not always inlined into OpenACC kernels, even with MFC's default two-pass IPO (-Mextract / -Minline=lib:), which does extract these routines into its inline library.

This leaves device CALL instructions to routines in m_eos and m_riemann_state across multiple simulation modules. The calls can force thread-private arrays into local memory and prevent optimizations across routine boundaries.

In a case-optimized 3D_performance_test build, we observed:

Metric master (3ef5e1e) Private inline copies
Device CALL sites to MFC routines (whole binary) 634 365
CALL sites in HLLC functions 140 6
HLLC kernel registers 127–159 146–148
HLLC kernel stack 528–576 B 48 B
HLLC kernel duration 2.45 ms 1.42 ms

Benchmarks on one NVIDIA H200 SXM (NVHPC 26.3, default build flags, --case-optimization) also show improvements:

Case Grind time improvement
3D_performance_test (WENO5, HLLC) −11.7%
3D_IGR_TaylorGreenVortex (IGR, Lax-Friedrichs) −10.5%

Grind time is measured in ns/gp/eq/rhs. Kernel duration was measured with the same change applied to an earlier master (42c44fd).

The 3D_performance_test output is bit-identical to master, and two runs of the same binary are identical. The 3D_IGR_TaylorGreenVortex case is not reproducible run to run even on master. Against master, its last step differs by at most 2.1e-15 relative to the field maximum. All 21 IGR tests in MFC's test suite, including the 3D_IGR_TaylorGreenVortex example test, pass at their existing tolerances.

Proposed solution

Make hot routines available for same-file inlining without changing their call sites or numerical formulas:

  • Move the EOS and per-face routine bodies into reusable Fypp macros (EOS_INLINE_PROCS and RS_INLINE_PROCS).
  • Keep their existing public definitions while expanding private copies in kernel-calling modules.
  • Preserve routine bodies, except for specializing f_is_state_dependent to .false. when case optimization excludes state-dependent EOS.

We propose using Fypp macros to share the routine bodies while allowing same-file inlining. Feedback on this approach or alternative implementations would be welcome.

One limitation is that future kernel-calling modules would need the same setup to benefit from inlining; otherwise, they continue to work through device calls.

Alternatives

Additional context

#2088 reports an HLLC performance regression, consistent with the local-memory overhead observed here.

Relationship to #2093: That PR removes device calls through targeted kernel restructuring, whereas this proposal enables inlining across existing calling modules without restructuring kernels.

For example, with --hllc-register-tuning enabled, #2093's HLLC kernel still has 14 device CALL sites in the same case-optimized 3D_performance_test build (NVHPC 26.3), all to routines this proposal covers. The proposed approach also covers calls from other solvers and simulation modules. In a local merge of the HLLC-related parts of both changes, those 14 calls are inlined as well.

The approaches are potentially complementary, although they overlap in f_is_state_dependent handling, in three routines that #2093 edits and this proposal moves into the macros, and in module imports in shared files.

A follow-up PR will provide the implementation. This issue is from Team NTHU SCC, participating in the SC26 Student Cluster Competition.

Activity

  1. aliencaocao commented on Oct 20, 2026

    @aliencaocao
    Contributor

    Agree that this is a better approach than #2093 that covers the non-fused code path (for cases where fused kernel cannot run on) due to less code change needed. I am agreeable to replace the implementation in #2093 with the approach proposed in this issue.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions