Crashed during execution with exit code 139 (segmentation fault).
After debugging, we found that the issue was related to two ROCm 7.x bugs on gfx1201 (RDNA4). These bugs caused GPU constant symbols and communication-related data access to fail under specific conditions.
Files modified:
cuda_params.hcuda_params.cu
In ROCm 7.x on gfx1201, __constant__ symbols declared inside:
namespace hemelb {}failed when accessed across different translation units (cross-TU) using:
hipMemcpyToSymbol(...)
hipGetSymbolAddress(...)The failure returned:
hipErrorInvalidKernelFileAs a result, the GPU constant variables were not initialized correctly, which caused the program to crash around NLookup.
We moved all __constant__ symbol declarations and definitions outside the hemelb namespace, placing them in the global scope.
We also added a new function:
hemelb::initGPUSymbolConstants(...)This function is implemented in cuda_params.cu and handles all GPU constant initialization inside the same translation unit.
The function performs:
hipGetSymbolAddress(...)
hipMemcpy(...)inside cuda_params.cu, avoiding the ROCm cross-TU symbol lookup issue.
File modified:
lb.hpparound line5867
Originally, lb.hpp directly called:
deviceMemcpyToSymbol(hemelb::_xxx, ...)for 11 different __constant__ symbols.
However, these operations accessed symbols across translation units. On ROCm 7.x with gfx1201, this caused symbol lookup failures and prevented the constants from being initialized correctly.
We replaced the 11 separate deviceMemcpyToSymbol(...) calls with a single call to:
hemelb::initGPUSymbolConstants(...)Since this function is defined in cuda_params.cu, the symbol address lookup and memory copy are performed in the same translation unit where the constants are defined.
This avoids the ROCm/gfx1201 cross-TU constant symbol issue.
File modified:
lb.hpparound line6034
The Smagorinsky constant symbol:
dev_smag_cnstwas moved from the hemelb namespace to the global scope.
However, the original code still referenced it as:
&hemelb::dev_smag_cnstAfter moving the symbol, this reference was no longer valid.
We changed the reference to explicitly use the global scope:
&::dev_smag_cnstThis correctly points to the global dev_smag_cnst symbol.
After applying Changes 1–3, the program successfully passed the previous crash point near NLookup.
The program completed initialization and printed:
Relaxation Time = 0.70000
It also successfully reached:
SIMULATION STARTING
This confirmed that the GPU constant initialization issue was resolved.
File modified:
lb.hpparound line255
When running with 1 GPU and 2 MPI ranks, Rank 1 does not have any GPU neighboring process.
In this case:
neighbouringProcsis an empty vector.
However, inside PostReceive(), the function:
Read_DistrFunctions_CPU_to_GPU_totalSharedFs()was still called.
That function accessed:
neighbouringProcs[0].FirstSharedDistributionSince neighbouringProcs was empty, its internal data pointer was null.
Accessing the first element caused the program to read from an invalid address:
0x10
This happened because FirstSharedDistribution is located at offset 16 bytes inside the struct. Therefore, accessing it from a null pointer resulted in:
NULL + 0x10 = 0x10
and caused a segmentation fault.
We added a guard at the beginning of the function:
if (totSharedFs == 0 || mLatDat->neighbouringProcs.empty()) return;This prevents the function from accessing neighbouringProcs[0] when there are no shared distributions or no neighboring GPU processes.
The main fixes include:
- Moved all GPU
__constant__symbols fromnamespace hemelbto global scope. - Added
hemelb::initGPUSymbolConstants(...)to initialize GPU constants insidecuda_params.cu. - Replaced cross-TU
deviceMemcpyToSymbol(...)calls inlb.hppwith one unified initialization function. - Updated
dev_smag_cnstaccess to use the global scope prefix::. - Added a safety guard for empty
neighbouringProcsin the 1-GPU case.
These changes fixed the ROCm/gfx1201 constant symbol initialization issue and prevented a segmentation fault caused by accessing an empty neighbouringProcs vector.