|
Orrery
A GPU-accelerated N-body gravitational simulator
|
Barnes-Hut with the traversal on a SYCL device. More...
#include <orrery/solvers/sycl_tree_solver.hpp>
Public Member Functions | |
| SyclTreeSolver (const SyclTreeSolver &)=delete | |
| SyclTreeSolver & | operator= (const SyclTreeSolver &)=delete |
| SyclTreeSolver (SyclTreeSolver &&) noexcept | |
| SyclTreeSolver & | operator= (SyclTreeSolver &&) 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 TreeParameters & | parameters () const noexcept |
| The tree parameters in force, after the corrections TreeParameters documents. | |
| const Octree & | tree () const noexcept |
| The tree the last evaluation built, empty before the first. | |
| TreeTraversal | traversal () const noexcept |
| Which traversal the next evaluation will run. | |
| void | select_traversal (TreeTraversal traversal) noexcept |
| void | select_sub_group_width (unsigned width) noexcept |
| Ask for a particular sub-group width, and settle for the device's own choice if it cannot provide that one. | |
| unsigned | sub_group_width () const noexcept |
| The width asked for, which is zero when the compiler is choosing. | |
| std::span< const unsigned > | supported_sub_group_widths () const noexcept |
| The widths this device will compile a kernel for, ascending. | |
| core::Index | work_group_size () const noexcept |
| The work-group size the traversal launches with. | |
| std::uint64_t | node_visits () const noexcept |
| How many nodes the traversal visited, summed over work-items, since the count was last reset. | |
| const backend::DeviceDescription & | device () const noexcept |
| What the runtime says about the device this solver runs on. | |
| const SyclTreeTimings & | timings () const noexcept |
| Where the last evaluation spent its time. | |
| bool | uses_shared_memory () const noexcept |
| Whether the arrays the traversal 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< SyclTreeSolver > | try_create (TreeParameters parameters={}, core::Softening softening={}, backend::Executor *executor=nullptr) |
| 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 |
Barnes-Hut with the traversal on a SYCL device.
Declared only where the backend is compiled, on the same terms as SyclDirectSolver. A caller that must work either way asks backend::kSyclBackendCompiled first.
|
staticnodiscard |
A solver on this machine's GPU, or nothing.
Returns null on the same three conditions SyclDirectSolver::try_create documents: no GPU, a device that cannot run this build's precision, or a runtime that fails to make a queue. None is an error and all three mean the caller should use the CPU tree solver, which computes the same thing.
executor schedules the host half, which is the sort and the tree build, and is referred to rather than owned. Null runs the host half on the calling thread. The result does not depend on which, since the ordering is total and the tree is a function of the sorted particles alone.
|
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. Safe to call with no particles.
Blocks until the device has finished, for the reason SyclDirectSolver::evaluate gives: there is nothing for the host to overlap the wait with, since the integrator cannot advance until the accelerations exist.
Implements orrery::integrators::AccelerationField.
|
inlinenodiscardoverridevirtualnoexcept |
The solver's name, for benchmark tables and test messages.
Implements orrery::solvers::ForceSolver.
|
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.
|
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.
|
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.
|
nodiscardnoexcept |
The tree the last evaluation built, empty before the first.
The host tree rather than the device copy, since the two describe the same cells and only this one can be inspected without a kernel. Exposed so that a benchmark can report the tree's shape beside its timing and a test can assert that the GPU and CPU solvers built the same tree.
|
noexcept |
Ask for a particular sub-group width, and settle for the device's own choice if it cannot provide that one.
Zero means the compiler chooses, which is the default and what a run should use. The knob exists because the width is the granularity of the coherence: it decides how many targets agree to walk together, and so sets both the redundancy the scheme costs and the divergence it removes. Sweeping it is the most direct measurement of the mitigation available, and docs/performance/sycl_tree.md reports the sweep.
Only widths the device reports are accepted, so a request the hardware cannot meet becomes the default rather than a submission that throws. supported_sub_group_widths says which those are.
|
nodiscardnoexcept |
The work-group size the traversal launches with.
A multiple of every sub-group width the device offers, since a work-group that is not one cannot be divided into whole sub-groups.
|
nodiscardnoexcept |
How many nodes the traversal visited, summed over work-items, since the count was last reset.
The measurement the phase turns on, and it means different things for the two traversals, which is the point of it. For the independent walk it is the sum of the lengths of the individual walks, which is the algorithm's own figure. For the coherent walk it is the sub-group's union walk counted once per lane, so the ratio between the two is exactly the redundancy coherence costs.
Reset by reset_interaction_count, alongside the interaction counters it belongs beside.
|
nodiscardnoexcept |
Whether the arrays the traversal reads are shared unified memory, asked of the runtime rather than assumed.
The same evidence SyclDirectSolver::uses_shared_memory provides, asked of the node array as well as of the particles, because the node array is the allocation this phase adds.