Skip to content

Class TempLat::GhostUpdater

template <size_t NDim>

ClassList > TempLat > GhostUpdater

A class which updates the ghost cells in our total memory block. By having the LayoutStruct , this class knows what is the ghostDepth.More...

  • #include <ghostupdater.h>

Public Static Attributes

Type Name
constexpr bool cCanNegate = requires(const U &x) { -x; }
Whether T supports unary minus, i.e. whether antiperiodic BCs are expressible for it at all. Only the fused kernel needs to ask: the per-component path reaches its negation through a branch that a non-negatable type never instantiates.
constexpr size_t cMaxLocalGhostBatch = 8
Largest component count the fused local ghost kernel handles in one launch. The widest batching caller today is SymTracelessField (5 components);SU2Field andSU2Doublet use 4. Wider batches fall back to the per-component path, so this is a capture-size budget rather than a correctness limit.

Public Functions

Type Name
GhostUpdater (MPICartesianExchange exchange, LayoutStruct< NDim > layout)
void applyLocalBCAtDimDepth (View & view, size_t dim, size_t depth, const device::IdxArray< NDim > & sizes, device::Idx ghostDepth, BCType bc, bool doLow=true, bool doHigh=true, bool mpiPostStep=false)
void applyLocalBCAtDimDepthBatch (std::span< MemoryBlock< T, NDim > *const > blocks, size_t dim, size_t depth, const device::IdxArray< NDim > & sizes, device::Idx ghostDepth, BCType bc)
Fused local BC ghost fill at one (dim, depth) across a batch of components.
void negatingCopySubview (const SrcView & src, DstView & dst)
void pUpdate_NOMPI (MemoryBlock< T, NDim > & block, BCSpec< NDim > bcSpec=allPeriodic< NDim >(), device::Idx dimension=0)
void pUpdate_NOMPI_batch (std::span< MemoryBlock< T, NDim > *const > blocks, std::span< const BCSpec< NDim > > bcSpecs)
Fused local ghost update over all dimensions for a batch of components.
void pUpdate_NOMPI_singleDim (MemoryBlock< T, NDim > & block, size_t dim, BCSpec< NDim > bcSpec=allPeriodic< NDim >())
Local BC-aware ghost copy for a single dimension (no MPI).
void pUpdate_NOMPI_singleDim_batch (std::span< MemoryBlock< T, NDim > *const > blocks, size_t dim, std::span< const BCSpec< NDim > > bcSpecs)
Fused local ghost update of one dimension across a batch of components.
void update (MemoryBlock< T, NDim > & block, BCSpec< NDim > bcSpec=allPeriodic< NDim >())
void updateBatch (std::span< MemoryBlock< T, NDim > *const > blocks, BCSpec< NDim > bcSpec=allPeriodic< NDim >())
Coalesced ghost update of several equally-shaped blocks (the components of a multi-component field). All faces of a given dimension/direction are packed into one buffer and exchanged in a single message, cutting the per-component message and synchronization count. The dimension sweep stays sequential so corner/edge ghosts remain correct. A batch of one is byte-identical to update().
void updateBatch (std::span< MemoryBlock< T, NDim > *const > blocks, std::span< const BCSpec< NDim > > bcSpecs)
updateBatch with per-component boundary conditions: bcSpecs[c] belongs toblocks[c] .
void update_forDimension_device (MemoryBlock< T, NDim > & block, size_t dimension, BCSpec< NDim > bcSpec=allPeriodic< NDim >())
void update_forDimension_device_batch (std::span< MemoryBlock< T, NDim > *const > blocks, size_t dimension, std::span< const BCSpec< NDim > > bcSpecs)
Coalesced GPU exchange of one split dimension for several blocks. Each component's face is packed into the shared slab buffers at its own contiguous offset (c * total_size), so the whole batch travels as one exchange (one P2P pull / one MPI message of C*total_size elements) with a single pack fence and a single unpack fence, instead of C separate exchanges + 2C fences. The send buffers grow to C * maxSlab and re-publish their IPC handles once per new maximum C.
~GhostUpdater ()

Public Static Functions

Type Name
DEVICE_INLINE_FUNCTION U negateIf (const U & v, bool neg)
neg ? -v : v , with the negation instantiated only whenU can be negated.

Detailed Description

Has one public method, update<T>(T* ptr), which, based on LayoutStruct, uses the associated subarrays and performs the exchange up and down in all dimensions, through calls to MPICartesianExchange with the appriate datatypes for the subarrays.

Unit test: ctest -R test-ghostupdater

Public Static Attributes Documentation

variable cCanNegate

Whether T supports unary minus, i.e. whether antiperiodic BCs are expressible for it at all. Only the fused kernel needs to ask: the per-component path reaches its negation through a branch that a non-negatable type never instantiates.

constexpr bool TempLat::GhostUpdater< NDim >::cCanNegate;


variable cMaxLocalGhostBatch

Largest component count the fused local ghost kernel handles in one launch. The widest batching caller today is SymTracelessField (5 components);SU2Field andSU2Doublet use 4. Wider batches fall back to the per-component path, so this is a capture-size budget rather than a correctness limit.

constexpr size_t TempLat::GhostUpdater< NDim >::cMaxLocalGhostBatch;


Public Functions Documentation

function GhostUpdater

inline TempLat::GhostUpdater::GhostUpdater (
    MPICartesianExchange exchange,
    LayoutStruct < NDim > layout
) 

function applyLocalBCAtDimDepth

template<typename T, typename View>
inline void TempLat::GhostUpdater::applyLocalBCAtDimDepth (
    View & view,
    size_t dim,
    size_t depth,
    const device::IdxArray< NDim > & sizes,
    device::Idx ghostDepth,
    BCType bc,
    bool doLow=true,
    bool doHigh=true,
    bool mpiPostStep=false
) 

function applyLocalBCAtDimDepthBatch

Fused local BC ghost fill at one (dim, depth) across a batch of components.

template<typename T>
inline void TempLat::GhostUpdater::applyLocalBCAtDimDepthBatch (
    std::span< MemoryBlock < T, NDim > *const > blocks,
    size_t dim,
    size_t depth,
    const device::IdxArray< NDim > & sizes,
    device::Idx ghostDepth,
    BCType bc
) 

applyLocalBCAtDimDepth issues two strided copyDeviceToDevice per component per (dim, depth) a low-face and a high-face copy. Over a full MC sweep that is ~1174 copies, against 70 actual sweep kernels, and at small volumes the launch count rather than the byte count is what costs. This does the same writes for every component in ONE kernel: 6C copies per pass collapse to 3 launches (one per dimension).

Unlike the MPI batch path there is no slab to pack a local wrap is a direct device-to-device move so the saving has to come from kernel fusion, not from coalescing messages. Indices are therefore computed in-kernel instead of via subviews, which also keeps the captured argument small (one view array, not four subview arrays).

Only the non-mpiPostStep semantics are implemented, which is all the local path needs; the MPI boundary post-step keeps using the per-component routine.


function negatingCopySubview

template<typename SrcView, typename DstView>
inline void TempLat::GhostUpdater::negatingCopySubview (
    const SrcView & src,
    DstView & dst
) 

function pUpdate_NOMPI

template<typename T>
inline void TempLat::GhostUpdater::pUpdate_NOMPI (
    MemoryBlock < T, NDim > & block,
    BCSpec< NDim > bcSpec=allPeriodic< NDim >(),
    device::Idx dimension=0
) 

function pUpdate_NOMPI_batch

Fused local ghost update over all dimensions for a batch of components.

template<typename T>
inline void TempLat::GhostUpdater::pUpdate_NOMPI_batch (
    std::span< MemoryBlock < T, NDim > *const > blocks,
    std::span< const BCSpec< NDim > > bcSpecs
) 

The dimension sweep stays outermost and sequential, which is what makes corner and edge ghosts correct: dimension d reads the ghosts that dimension d-1 just wrote. Note this inverts the loop nesting relative to for (b : blocks) pUpdate_NOMPI(*b), which is component-outer / dimension-inner. That is safe because components are independent allocations what must be ordered is the dimensions within a component, and every component still sees them in the same order.


function pUpdate_NOMPI_singleDim

Local BC-aware ghost copy for a single dimension (no MPI).

template<typename T>
inline void TempLat::GhostUpdater::pUpdate_NOMPI_singleDim (
    MemoryBlock < T, NDim > & block,
    size_t dim,
    BCSpec< NDim > bcSpec=allPeriodic< NDim >()
) 


function pUpdate_NOMPI_singleDim_batch

Fused local ghost update of one dimension across a batch of components.

template<typename T>
inline void TempLat::GhostUpdater::pUpdate_NOMPI_singleDim_batch (
    std::span< MemoryBlock < T, NDim > *const > blocks,
    size_t dim,
    std::span< const BCSpec< NDim > > bcSpecs
) 


function update

template<typename T>
inline void TempLat::GhostUpdater::update (
    MemoryBlock < T, NDim > & block,
    BCSpec< NDim > bcSpec=allPeriodic< NDim >()
) 

function updateBatch [1/2]

Coalesced ghost update of several equally-shaped blocks (the components of a multi-component field). All faces of a given dimension/direction are packed into one buffer and exchanged in a single message, cutting the per-component message and synchronization count. The dimension sweep stays sequential so corner/edge ghosts remain correct. A batch of one is byte-identical to update().

template<typename T>
inline void TempLat::GhostUpdater::updateBatch (
    std::span< MemoryBlock < T, NDim > *const > blocks,
    BCSpec< NDim > bcSpec=allPeriodic< NDim >()
) 

This overload applies one bcSpec to every block in the batch; see the per-component overload below for fields whose components differ.


function updateBatch [2/2]

updateBatch with per-component boundary conditions: bcSpecs[c] belongs toblocks[c] .

template<typename T>
inline void TempLat::GhostUpdater::updateBatch (
    std::span< MemoryBlock < T, NDim > *const > blocks,
    std::span< const BCSpec< NDim > > bcSpecs
) 

Components of one field disagreeing on their BC is not pathological — it is what C-star boundary conditions are. The identification Phi(x + L) = Phi*(x) is, in the real-component basis these fields are stored in, a sign flip on some components and not others: (c0, c1, c2, c3) -> (c0, -c1, c2, -c3) for both an SU(2) group element and an SU(2) doublet, (Re, Im) -> (Re, -Im) for a complex scalar. So a batch legitimately carries a mixture of Periodic and Antiperiodic.

Nothing about the coalescing depends on uniformity: the exchange is BC-agnostic (it just lands the global-wrap value in every ghost slab) and the BC is a per-block post-step that was already written as a loop over the batch. Only the fused local kernel needs care — see pUpdate_NOMPI_singleDim_batch.


function update_forDimension_device

template<typename T>
inline void TempLat::GhostUpdater::update_forDimension_device (
    MemoryBlock < T, NDim > & block,
    size_t dimension,
    BCSpec< NDim > bcSpec=allPeriodic< NDim >()
) 

function update_forDimension_device_batch

Coalesced GPU exchange of one split dimension for several blocks. Each component's face is packed into the shared slab buffers at its own contiguous offset (c * total_size), so the whole batch travels as one exchange (one P2P pull / one MPI message of C*total_size elements) with a single pack fence and a single unpack fence, instead of C separate exchanges + 2C fences. The send buffers grow to C * maxSlab and re-publish their IPC handles once per new maximum C.

template<typename T>
inline void TempLat::GhostUpdater::update_forDimension_device_batch (
    std::span< MemoryBlock < T, NDim > *const > blocks,
    size_t dimension,
    std::span< const BCSpec< NDim > > bcSpecs
) 


function ~GhostUpdater

inline TempLat::GhostUpdater::~GhostUpdater () 

Public Static Functions Documentation

function negateIf

neg ? -v : v , with the negation instantiated only whenU can be negated.

template<typename U>
static inline DEVICE_INLINE_FUNCTION U TempLat::GhostUpdater::negateIf (
    const U & v,
    bool neg
) 

A free function rather than a if constexpr inside the kernel body: nvcc rejects an extended host device lambda that first-captures a variable inside a constexpr-if context, which is exactly what capturing negate there amounts to ("cannot first-capture variable in constexpr-if context"). Confining the branch to a named DEVICE_INLINE_FUNCTION keeps the lambda's captures unconditional.

The else branch is unreachable in practice applyLocalBCAtDimDepthBatch throws before launch if antiperiodic BCs are asked of a non-negatable type so it exists to make the kernel compile for such types, not to define behaviour for them.



The documentation for this class was generated from the following file cosmolatticeweb/tmp/code_source/templat/include/TempLat/lattice/ghostcells/ghostupdater.h