LinearInterpolator1D< NT, Coordinates > Class Template Reference#

DiFfRG: DiFfRG::LinearInterpolator1D< NT, Coordinates > Class Template Reference
DiFfRG
Discretization Framework for functional Renormalization Group flows

A linear interpolator for 1D data, callable from host AND device code. More...

#include <linear_interpolator_1d.hh>

Public Types

using ctype = typename Coordinates::ctype
 
using value_type = NT
 

Public Member Functions

 LinearInterpolator1D (const Coordinates &coordinates)
 Construct a LinearInterpolator1D with internal, zeroed data and a coordinate system.
 
KOKKOS_DEFAULTED_FUNCTION LinearInterpolator1D (const LinearInterpolator1D &)=default
 Shallow copy of BOTH views, valid in host and in device code.
 
template<typename NT2 >
void update (const NT2 *in_data)
 Replace the data, leaving host AND device current. The only mutator.
 
NT operator[] (size_t i) const
 Host-side element access. Always valid, including on a copy.
 
Coordinates::ctype KOKKOS_FUNCTION index (const typename Coordinates::ctype x) const
 Map a physical coordinate onto the grid index.
 
NT KOKKOS_FUNCTION at (const typename Coordinates::ctype idx) const
 Interpolate at a grid index previously obtained from index().
 
NT KOKKOS_FUNCTION operator() (const typename Coordinates::ctype x) const
 Interpolate the data at a given point.
 
const Coordinates & get_coordinates () const
 Get the coordinate system of the data.
 
const NT * data () const
 Read-only handle to the host values.
 

Static Public Attributes

static constexpr size_t dim = 1
 

Private Types

using ViewType = Kokkos::View<NT *, GPU_memory, Kokkos::MemoryTraits<Kokkos::RandomAccess>>
 
using HostViewType = typename ViewType::host_mirror_type
 

Private Member Functions

KOKKOS_FORCEINLINE_FUNCTION NT value (const size_t i) const
 Read one element from whichever buffer belongs to the executing side.
 

Private Attributes

const Coordinates coordinates
 
const size_t size
 
ViewType device_data
 
HostViewType host_data
 

Static Private Attributes

static constexpr bool periodic = is_periodic_coordinate_v<Coordinates>
 
static constexpr bool has_separate_device
 

Detailed Description

template<typename NT, typename Coordinates>
class DiFfRG::LinearInterpolator1D< NT, Coordinates >

A linear interpolator for 1D data, callable from host AND device code.

The object owns one device-resident allocation and its host mirror, and update() leaves both current. There is therefore no memory-space template parameter and no lazily built twin in the other space: at() simply reads whichever buffer belongs to the side it is executing on.

That dispatch cannot be an if constexpr. "Am I on the device" is a property of the compilation pass, not of a template argument, and only CUDA_ARCH carries it. Under nvcc with a GNU host compiler KOKKOS_IF_ON_DEVICE/KOKKOS_IF_ON_HOST are a plain preprocessor selection (Kokkos_Macros.hpp; the NV_IF_TARGET spelling there is gated on KOKKOS_COMPILER_NVHPC, which this build does not use), so each pass compiles exactly one body and each pass ends in a return. This is NOT the nvcc extended-lambda if constexpr miscompile documented in quadrature_integrator.hh – that one is about lambda bodies.

If the dispatch is ever wrong the failure is loud rather than silent: View::operator() runs runtime_check_memory_access_violation, which Kokkos::abort()s with "attempt to access inaccessible memory space". See tests/physics/interpolation/host_device_dispatch.cc.

Template Parameters
NTinput data type
Coordinatescoordinate system of the input data

Member Typedef Documentation

◆ ctype

template<typename NT , typename Coordinates >
using DiFfRG::LinearInterpolator1D< NT, Coordinates >::ctype = typename Coordinates::ctype

◆ HostViewType

template<typename NT , typename Coordinates >
using DiFfRG::LinearInterpolator1D< NT, Coordinates >::HostViewType = typename ViewType::host_mirror_type
private

◆ value_type

template<typename NT , typename Coordinates >
using DiFfRG::LinearInterpolator1D< NT, Coordinates >::value_type = NT

◆ ViewType

template<typename NT , typename Coordinates >
using DiFfRG::LinearInterpolator1D< NT, Coordinates >::ViewType = Kokkos::View<NT *, GPU_memory, Kokkos::MemoryTraits<Kokkos::RandomAccess>>
private

Constructor & Destructor Documentation

◆ LinearInterpolator1D() [1/2]

template<typename NT , typename Coordinates >
DiFfRG::LinearInterpolator1D< NT, Coordinates >::LinearInterpolator1D ( const Coordinates & coordinates)
inline

Construct a LinearInterpolator1D with internal, zeroed data and a coordinate system.

Parameters
coordinatescoordinate system of the data

◆ LinearInterpolator1D() [2/2]

template<typename NT , typename Coordinates >
KOKKOS_DEFAULTED_FUNCTION DiFfRG::LinearInterpolator1D< NT, Coordinates >::LinearInterpolator1D ( const LinearInterpolator1D< NT, Coordinates > & )
default

Shallow copy of BOTH views, valid in host and in device code.

Carrying the HostSpace mirror into a device closure is exactly what Kokkos::DualView does: the view tracker force-disables reference counting on the device side, so the host pointer is copied and never dereferenced there. Defaulted rather than user-defined, because a host-only copy constructor makes capture into a KOKKOS_LAMBDA ill-formed.

Member Function Documentation

◆ at()

template<typename NT , typename Coordinates >
NT KOKKOS_FUNCTION DiFfRG::LinearInterpolator1D< NT, Coordinates >::at ( const typename Coordinates::ctype idx) const
inline

Interpolate at a grid index previously obtained from index().

◆ data()

template<typename NT , typename Coordinates >
const NT * DiFfRG::LinearInterpolator1D< NT, Coordinates >::data ( ) const
inline

Read-only handle to the host values.

Deliberately const: there is no public way to push a host-side edit to the device, so a write handle could only ever desynchronize the two. Route mutations through update().

◆ get_coordinates()

template<typename NT , typename Coordinates >
const Coordinates & DiFfRG::LinearInterpolator1D< NT, Coordinates >::get_coordinates ( ) const
inline

Get the coordinate system of the data.

Returns
const Coordinates& the coordinate system

◆ index()

template<typename NT , typename Coordinates >
Coordinates::ctype KOKKOS_FUNCTION DiFfRG::LinearInterpolator1D< NT, Coordinates >::index ( const typename Coordinates::ctype x) const
inline

Map a physical coordinate onto the grid index.

Split out for the same reason as in SplineInterpolator1D: for a logarithmic or focused-log axis Coordinates::backward is a fp64 log/log1p costing ~200 fp64 instructions, and a kernel evaluating several dressings at one momentum otherwise pays it once per dressing (the compiler cannot CSE it, since each interpolator owns its own coordinate members).

Depends only on the coordinate system, so the result may be shared across interpolators that share one – stencil resolution and clamping stay in at().

◆ operator()()

template<typename NT , typename Coordinates >
NT KOKKOS_FUNCTION DiFfRG::LinearInterpolator1D< NT, Coordinates >::operator() ( const typename Coordinates::ctype x) const
inline

Interpolate the data at a given point.

◆ operator[]()

template<typename NT , typename Coordinates >
NT DiFfRG::LinearInterpolator1D< NT, Coordinates >::operator[] ( size_t i) const
inline

Host-side element access. Always valid, including on a copy.

◆ update()

template<typename NT , typename Coordinates >
template<typename NT2 >
void DiFfRG::LinearInterpolator1D< NT, Coordinates >::update ( const NT2 * in_data)
inline

Replace the data, leaving host AND device current. The only mutator.

The mirror is filled by a plain host copy rather than a Kokkos::deep_copy. A deep_copy dispatches onto an execution space and would have to be fenced before the H2D below could be enqueued; a memcpy/loop is complete when it returns. That is what leaves exactly one fence in this function.

The trailing fence is NOT optional: it is what lets the caller refill host_data on the next update() without racing an in-flight H2D copy. Dropping it requires double-buffering the host staging array.

The H2D names an execution space instance. The space-less deep_copy brackets EVERY copy in a global Kokkos::fence() that synchronizes all execution space instances of all enabled backends – measured at ~11.4 cudaDeviceSynchronize calls per copy, i.e. ~98k device-wide barriers in a single 425-RHS YangMills solve. This copy only needs to be ordered against the kernels that read it, which share this execution space instance.

◆ value()

template<typename NT , typename Coordinates >
KOKKOS_FORCEINLINE_FUNCTION NT DiFfRG::LinearInterpolator1D< NT, Coordinates >::value ( const size_t i) const
inlineprivate

Read one element from whichever buffer belongs to the executing side.

Member Data Documentation

◆ coordinates

template<typename NT , typename Coordinates >
const Coordinates DiFfRG::LinearInterpolator1D< NT, Coordinates >::coordinates
private

◆ device_data

template<typename NT , typename Coordinates >
ViewType DiFfRG::LinearInterpolator1D< NT, Coordinates >::device_data
private

◆ dim

template<typename NT , typename Coordinates >
size_t DiFfRG::LinearInterpolator1D< NT, Coordinates >::dim = 1
staticconstexpr

◆ has_separate_device

template<typename NT , typename Coordinates >
bool DiFfRG::LinearInterpolator1D< NT, Coordinates >::has_separate_device
staticconstexprprivate
Initial value:
=
!std::is_same_v<typename ViewType::memory_space, typename HostViewType::memory_space>

◆ host_data

template<typename NT , typename Coordinates >
HostViewType DiFfRG::LinearInterpolator1D< NT, Coordinates >::host_data
private

◆ periodic

template<typename NT , typename Coordinates >
bool DiFfRG::LinearInterpolator1D< NT, Coordinates >::periodic = is_periodic_coordinate_v<Coordinates>
staticconstexprprivate

◆ size

template<typename NT , typename Coordinates >
const size_t DiFfRG::LinearInterpolator1D< NT, Coordinates >::size
private

The documentation for this class was generated from the following file: