Orrery
A GPU-accelerated N-body gravitational simulator
Loading...
Searching...
No Matches
orrery::solvers::SyclDirectSolver Class Referencefinal

Direct summation evaluated on a SYCL device. More...

#include <orrery/solvers/sycl_direct_solver.hpp>

Inheritance diagram for orrery::solvers::SyclDirectSolver:
orrery::solvers::ForceSolver orrery::integrators::AccelerationField

Public Member Functions

 SyclDirectSolver (const SyclDirectSolver &)=delete
SyclDirectSolver & operator= (const SyclDirectSolver &)=delete
 SyclDirectSolver (SyclDirectSolver &&) noexcept
SyclDirectSolver & operator= (SyclDirectSolver &&) noexcept
void evaluate (core::Vec3Span< const core::Real > positions, std::span< const core::Real > masses, core::Vec3Span< core::Real > accelerations) override
 Write the acceleration at each position into accelerations.
std::string_view name () const noexcept override
 The solver's name, for benchmark tables and test messages.
core::Softening softening () const noexcept override
 The softening this solver applies.
InteractionCount interaction_count () const noexcept override
 The work done since construction or since the last reset.
void reset_interaction_count () noexcept override
 Set every counter back to zero.
const backend::DeviceDescriptiondevice () const noexcept
 What the runtime says about the device this solver runs on.
core::Index tile_size () const noexcept
 How many sources are staged through local memory at a time, which is also the work-group size.
const SyclEvaluationTimingstimings () const noexcept
 Where the last evaluation spent its time.
bool uses_shared_memory () const noexcept
 Whether the arrays the kernel reads are shared unified memory, asked of the runtime rather than assumed.
Public Member Functions inherited from orrery::solvers::ForceSolver
 ~ForceSolver () override=default
 Public and virtual, the second by inheritance from AccelerationField.

Static Public Member Functions

static std::unique_ptr< SyclDirectSolver > try_create (core::Softening softening={})
 A solver on this machine's GPU, or nothing.

Additional Inherited Members

Protected Member Functions inherited from orrery::solvers::ForceSolver
 ForceSolver (const ForceSolver &)=default
 ForceSolver (ForceSolver &&)=default
ForceSolver & operator= (const ForceSolver &)=default
ForceSolver & operator= (ForceSolver &&)=default
Protected Member Functions inherited from orrery::integrators::AccelerationField
 AccelerationField (const AccelerationField &)=default
 AccelerationField (AccelerationField &&)=default
AccelerationField & operator= (const AccelerationField &)=default
AccelerationField & operator= (AccelerationField &&)=default

Detailed Description

Direct summation evaluated on a SYCL device.

Declared only where the backend is compiled, following the precedent ORRERY_HAS_AVX2_KERNEL sets in solvers/direct_kernel.hpp. A caller that must work either way asks backend::kSyclBackendCompiled first, which is a constant and available in every build.

Member Function Documentation

◆ try_create()

std::unique_ptr< SyclDirectSolver > orrery::solvers::SyclDirectSolver::try_create ( core::Softening softening = {})
staticnodiscard

A solver on this machine's GPU, or nothing.

Returns null when there is no GPU, when the device cannot run the precision this build was configured for, or when the runtime fails to create a queue. All three mean the same thing to a caller, which is that this machine cannot run the kernel and the CPU solver should be used instead, and none of them is an error worth an exception: a laptop with no usable device is an ordinary machine, not a broken one.

A factory rather than a constructor precisely because construction can fail for reasons that are not faults. A constructor has only one way to report failure and section 4 reserves that for setup errors.

◆ evaluate()

void orrery::solvers::SyclDirectSolver::evaluate ( core::Vec3Span< const core::Real > positions,
std::span< const core::Real > masses,
core::Vec3Span< core::Real > accelerations )
overridevirtual

Write the acceleration at each position into accelerations.

The three views must describe the same particles in the same order and have the same length, as AccelerationField requires and as the CPU solver documents. Safe to call with no particles.

Blocks until the device has finished. An asynchronous interface would be the right shape for overlapping the force evaluation with something else, and there is nothing else: the integrator cannot advance until the accelerations exist.

Implements orrery::integrators::AccelerationField.

◆ name()

std::string_view orrery::solvers::SyclDirectSolver::name ( ) const
inlinenodiscardoverridevirtualnoexcept

The solver's name, for benchmark tables and test messages.

Implements orrery::solvers::ForceSolver.

◆ softening()

core::Softening orrery::solvers::SyclDirectSolver::softening ( ) const
nodiscardoverridevirtualnoexcept

The softening this solver applies.

Exposed so that a caller measuring energies asks the solver what it softened with rather than carrying a second copy of the value alongside it. Two copies of a number that must agree are how they come to disagree, and a potential energy computed with a different softening from the force kernel turns the project's headline conservation result into a measurement of the mismatch (ADR-0008).

Implements orrery::solvers::ForceSolver.

◆ interaction_count()

InteractionCount orrery::solvers::SyclDirectSolver::interaction_count ( ) const
nodiscardoverridevirtualnoexcept

The work done since construction or since the last reset.

Cheap: solvers accumulate this as they go and this call only reads it.

Implements orrery::solvers::ForceSolver.

◆ reset_interaction_count()

void orrery::solvers::SyclDirectSolver::reset_interaction_count ( )
overridevirtualnoexcept

Set every counter back to zero.

A benchmark counts the work of the measured region rather than of the warm-up that preceded it, and the two are otherwise indistinguishable once they have been added together.

Implements orrery::solvers::ForceSolver.

◆ device()

const backend::DeviceDescription & orrery::solvers::SyclDirectSolver::device ( ) const
nodiscardnoexcept

What the runtime says about the device this solver runs on.

Exposed because no GPU figure means anything without it. A throughput number from an integrated part and one from a discrete card are not comparable, and neither is the same part on a different driver.

◆ tile_size()

core::Index orrery::solvers::SyclDirectSolver::tile_size ( ) const
nodiscardnoexcept

How many sources are staged through local memory at a time, which is also the work-group size.

Chosen from what the device reports rather than fixed, and reported so that a benchmark states it alongside the timing it produced.

◆ uses_shared_memory()

bool orrery::solvers::SyclDirectSolver::uses_shared_memory ( ) const
nodiscardnoexcept

Whether the arrays the kernel reads are shared unified memory, asked of the runtime rather than assumed.

This is the evidence behind Phase 9's zero-copy requirement, reachable from a test and from the benchmark that reports it. backend/sycl_usm.hpp explains what the question means and why the answer is not simply "I called the shared allocator".


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