Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rename VirtualRecord into RecordRef #551

Merged
merged 1 commit into from
Jul 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/images/overview.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ LLAMA is licensed under the LGPL3+.
pages/introduction
pages/dimensions
pages/views
pages/virtualrecord
pages/recordref
pages/iteration
pages/mappings
pages/proxyreferences
Expand Down
4 changes: 2 additions & 2 deletions docs/pages/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ View creation
.. doxygenfunction:: llama::allocViewUninitialized
.. doxygenfunction:: llama::allocViewStack
.. doxygentypedef:: llama::One
.. doxygenfunction:: llama::copyVirtualRecordStack
.. doxygenfunction:: llama::copyRecord

.. _label-api-bloballocators:

Expand Down Expand Up @@ -197,7 +197,7 @@ Data access
:members:
.. doxygenstruct:: llama::VirtualView
:members:
.. doxygenstruct:: llama::VirtualRecord
.. doxygenstruct:: llama::RecordRef
:members:

Copying
Expand Down
4 changes: 2 additions & 2 deletions docs/pages/introduction.rst
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ The data space is an hypercubic index set described by the record dimension and
The record dimension consists of a hierarchy of names and describes nested, structured data, much like a :cpp:`struct` in C++.
The array dimensions are zero-based integral ranges.
Programs are written against this abstract data space and thus formulated independent of the physical manifestation of the data space.
Programs can refer to subparts of the data space via virtual records or real l-value references.
Programs can refer to subparts of the data space via record references or real l-value references.
The data space is materialized via a mapping that describes how the index set of the data space is embedded into a physical memory.
This mapping is exchangeable at compile time and can be augmented with additional information from the programs access pattern and target hardware information.
Due to a mapping encapsulating the full knowledge of a memory layout, LLAMA supports layout aware copies between instances of the same data space but with different mappings.
Expand All @@ -110,7 +110,7 @@ LLAMA comes with a set of predefined blob allocators and users can again provide
Once a view is created, the user can navigate on the data managed by the view.
On top of a view, a :ref:`VirtualView <label-virtualview>` can be created, offering access to a subspace of the array dimensions.
Elements of the array dimensions, called records, are accessed on both, View and VirtualView, by calling :cpp:`operator()` with an array index as instance of :cpp:`ArrayIndex`.
This access returns a :ref:`VirtualRecord <label-virtualrecord>`, allowing further access using the tags from the record dimension, until eventually a reference to actual data in memory is returned.
This access returns a :ref:`RecordRef <label-recordref>`, allowing further access using the tags from the record dimension, until eventually a reference to actual data in memory is returned.


Example use cases
Expand Down
6 changes: 3 additions & 3 deletions docs/pages/llama_vs_cpp.rst
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ Values and references
- .. code:: C++

auto p = view[i];
// decltype(p) == llama::VirtualRecord<...>
// decltype(p) == llama::RecordRef<...>
- .. code:: C++

auto&& p = view[i];
Expand Down Expand Up @@ -187,7 +187,7 @@ Values and references
- .. code:: C++

auto v = view[i](Pos{});
// decltype(v) == llama::VirtualRecord<...>
// decltype(v) == llama::RecordRef<...>
- .. code:: C++

auto&& v = view[i](Pos{});
Expand Down Expand Up @@ -245,7 +245,7 @@ Values and references


Notice that the use of :cpp:`auto` to declare a local copy of a value read through a reference, e.g. :cpp:`auto pos = view[i].pos; // copy`, does not work as expected in LLAMA.
LLAMA makes extensive use of proxy reference types (including :cpp:`llama::VirtualRecord`),
LLAMA makes extensive use of proxy reference types (including :cpp:`llama::RecordRef`),
where a reference is sometimes represented as a value and sometimes as a real C++ reference.
The only consistent way to deal with this duality in LLAMA is the use a forwarding reference :cpp:`auto&&`
when we want to have a reference (native or proxy) into a LLAMA data structure,
Expand Down
2 changes: 1 addition & 1 deletion docs/pages/mappings.rst
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ One
---

The One mapping is intended to map all coordinates in the array dimensions onto the same memory location.
This is commonly used in the :cpp:`llama::One` virtual record, but also offers interesting applications in conjunction with the :cpp:`llama::mapping::Split` mapping.
This is commonly used in :cpp:`llama::One`, but also offers interesting applications in conjunction with the :cpp:`llama::mapping::Split` mapping.


Split
Expand Down
16 changes: 8 additions & 8 deletions docs/pages/proxyreferences.rst
Original file line number Diff line number Diff line change
Expand Up @@ -80,31 +80,31 @@ Proxy references in LLAMA
-------------------------

By handing out references to access contained objects, LLAMA views are similar to standard C++ containers.
For references to whole records, LLAMA views hand out virtual records.
Although a virtual record models a reference to a struct (= record) in memory, this struct is not physically manifested in memory.
For references to whole records, LLAMA views hand out record references.
Although a record reference models a reference to a struct (= record) in memory, this struct is not physically manifested in memory.
This allows mappings the freedom to arbitrarily arrange how the data for a struct is stored.
A virtual record in LLAMA is thus conceptually a proxy reference.
A record reference in LLAMA is thus a proxy reference.
An exception is however made for read/write access in the current API, which is governed by the :cpp:`load()` and :cpp:`store()` member functions.
We might change this in the future.

.. code-block:: C++

auto view = llama::allocView(...);
auto vr = view(1, 2, 3); // vr is a VirtualRecord, a proxy reference
Pixel p = vr.load(); // read access
vr.store(p); // write access
auto rr = view(1, 2, 3); // vr is a RecordRef, a proxy reference
Pixel p = rr.load(); // read access
rr.store(p); // write access

Similarly, some mappings choose a different in-memory representation for the field types in the leaves of the record dimension.
Examples are the :cpp:`Bytesplit`, :cpp:`ChangeType`, :cpp:`BitPackedIntSoa` or :cpp:`BitPackedFloatSoa` mappings.
These mappings even return a proxy reference for terminal accesses:

.. code-block:: C++

auto&& ref = vr(color{}, r{}); // may be a float& or a proxy reference object, depending on the mapping
auto&& ref = rr(color{}, r{}); // may be a float& or a proxy reference object, depending on the mapping

Thus, when you want to write truly generic code with LLAMA's views, please keep these guidelines in mind:

* Each non-terminal access on a view returns a virtual record, which is a value-type with reference semantic.
* Each non-terminal access on a view returns a record reference, which is a value-type with reference semantic.
* Each terminal access on a view may return an l-value reference or a proxy reference.
Thus use :cpp:`auto&&` to handle both cases.
* Explicitly specify the type of copies of individual fields you want to make from references obtains from a LLAMA view.
Expand Down
56 changes: 28 additions & 28 deletions docs/pages/virtualrecord.rst → docs/pages/recordref.rst
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
.. include:: common.rst

.. _label-virtualrecord:
.. _label-recordref:

VirtualRecord
=============
RecordRef
=========

During a view accesses like :cpp:`view(1, 2, 3)(color{}, g{})` an intermediate object is needed for this to work.
This object is a :cpp:`llama::VirtualRecord`.
This object is a :cpp:`llama::RecordRef`.

.. code-block:: C++

Expand All @@ -28,25 +28,25 @@ This object is a :cpp:`llama::VirtualRecord`.
float& g = vdColor(g{});
g = 1.0;

Supplying the array dimensions coordinate to a view access returns such a :cpp:`llama::VirtualRecord`, storing this array dimensions coordinate.
This object can be thought of like a record in the :math:`N`-dimensional array dimensions space,
but as the fields of this record may not be contiguous in memory, it is not a real object in the C++ sense and thus called virtual.
Supplying the array dimensions coordinate to a view access returns such a :cpp:`llama::RecordRef`, storing this array dimensions coordinate.
This object models a reference to a record in the :math:`N`-dimensional array dimensions space,
but as the fields of this record may not be contiguous in memory, it is not a native l-value reference.

Accessing subparts of a :cpp:`llama::VirtualRecord` is done using :cpp:`operator()` and the tag types from the record dimension.
Accessing subparts of a :cpp:`llama::RecordRef` is done using :cpp:`operator()` and the tag types from the record dimension.

If an access describes a final/leaf element in the record dimension, a reference to a value of the corresponding type is returned.
Such an access is called terminal. If the access is non-terminal, i.e. it does not yet reach a leaf in the record dimension tree,
another :cpp:`llama::VirtualRecord` is returned, binding the tags already used for navigating down the record dimension.
another :cpp:`llama::RecordRef` is returned, binding the tags already used for navigating down the record dimension.

A :cpp:`llama::VirtualRecord` can be used like a real local object in many places. It can be used as a local variable, copied around, passed as an argument to a function (as seen in the
A :cpp:`llama::RecordRef` can be used like a real local object in many places. It can be used as a local variable, copied around, passed as an argument to a function (as seen in the
`nbody example <https://github.com/alpaka-group/llama/blob/master/examples/nbody/nbody.cpp>`_), etc.
In general, :cpp:`llama::VirtualRecord` is a value type that represents a reference, similar to an iterator in C++ (:cpp:`llama::One` is a notable exception).
In general, :cpp:`llama::RecordRef` is a value type that represents a reference, similar to an iterator in C++ (:cpp:`llama::One` is a notable exception).


One
---

:cpp:`llama::One<RecordDim>` is a shortcut to create a scalar :cpp:`llama::VirtualRecord`.
:cpp:`llama::One<RecordDim>` is a shortcut to create a scalar :cpp:`llama::RecordRef`.
This is useful when we want to have a single record instance e.g. as a local variable.

.. code-block:: C++
Expand All @@ -55,14 +55,14 @@ This is useful when we want to have a single record instance e.g. as a local var
pixel(color{}, g{}) = 1.0;
auto pixel2 = pixel; // independent copy

Technically, :cpp:`llama::One` is a :cpp:`llama::VirtualRecord` which stores a scalar :cpp:`llama::View` inside, using the mapping :cpp:`llama::mapping::One`.
Technically, :cpp:`llama::One` is a :cpp:`llama::RecordRef` which stores a scalar :cpp:`llama::View` inside, using the mapping :cpp:`llama::mapping::One`.
This also has the consequence that a :cpp:`llama::One` is now a value type with deep-copy semantic.


Arithmetic and logical operators
--------------------------------

:cpp:`llama::VirtualRecord` overloads several operators:
:cpp:`llama::RecordRef` overloads several operators:

.. code-block:: C++

Expand All @@ -75,8 +75,8 @@ Arithmetic and logical operators
foobar(record2);

//With this somewhere else:
template<typename VirtualRecord>
void foobar(VirtualRecord vr)
template<typename RecordRef>
void foobar(RecordRef vr)
{
vr = 42;
}
Expand All @@ -86,7 +86,7 @@ These operators directly write into the corresponding view.
Furthermore, the binary, non-bitwise, arithmetic operators ( :cpp:`+`, :cpp:`-`, :cpp:`*`, :cpp:`/`, :cpp:`%` ) are overloaded too,
but they return a temporary object on the stack (i.e. a :cpp:`llama::One`).

These operators work between two virtual records, even if they have different record dimensions.
These operators work between two record references, even if they have different record dimensions.
Every tag existing in both record dimensions will be matched and operated on.
Every non-matching tag is ignored, e.g.

Expand Down Expand Up @@ -121,7 +121,7 @@ Every non-matching tag is ignored, e.g.
// record2.mom.x will be multiplied to record2.vel.x as the first part of the
// record dimension coord is explicit given and the same afterwards

The discussed operators are also overloaded for types other than :cpp:`llama::VirtualRecord` as well so that
The discussed operators are also overloaded for types other than :cpp:`llama::RecordRef` as well so that
:cpp:`record1 *= 7.0` will multiply 7 to every element in the record dimension.
This feature should be used with caution!

Expand Down Expand Up @@ -167,8 +167,8 @@ Let's examine this deeper in an example:
result = a2 == b;
//result is true, because only the matching "x" matters

A partial addressing of a virtual record like :cpp:`record1(color{}) *= 7.0` is also possible.
:cpp:`record1(color{})` itself returns a new virtual record with the first record dimension coordinate (:cpp:`color`) being bound.
A partial addressing of a record reference like :cpp:`record1(color{}) *= 7.0` is also possible.
:cpp:`record1(color{})` itself returns a new record reference with the first record dimension coordinate (:cpp:`color`) being bound.
This enables e.g. to easily add a velocity to a position like this:

.. code-block:: C++
Expand All @@ -186,7 +186,7 @@ This enables e.g. to easily add a velocity to a position like this:
>>,
>;

// Let record be a virtual record with the record dimension "Particle".
// Let record be a record reference with the record dimension "Particle".

record(pos{}) += record(vel{});

Expand All @@ -197,9 +197,9 @@ Tuple interface
WARNING: This is an experimental feature and might completely change in the future.

A struct in C++ can be modelled by a :cpp:`std::tuple` with the same types as the struct's members.
A :cpp:`llama::VirtualRecord` behaves like a reference to a struct (i.e. the record) which is decomposed into it's members.
A :cpp:`llama::RecordRef` behaves like a reference to a struct (i.e. the record) which is decomposed into it's members.
We can therefore not form a single reference to such a record, but references to the individual members.
Organizing these references inside a :cpp:`std::tuple` in the same way the record is represented in the record dimension gives us an alternative to a :cpp:`llama::VirtualRecord`.
Organizing these references inside a :cpp:`std::tuple` in the same way the record is represented in the record dimension gives us an alternative to a :cpp:`llama::RecordRef`.
Mind that creating such a :cpp:`std::tuple` already invokes the mapping function, regardless of whether an actual memory access occurs through the constructed reference later.
However, such dead address computations are eliminated by most compilers during optimization.

Expand All @@ -210,7 +210,7 @@ However, such dead address computations are eliminated by most compilers during
std::tuple<float&, float&, float&, char&> = record.asFlatTuple();
auto [r, g, b, a] = record.asFlatTuple();

Additionally, if the user already has types supporting the C++ tuple interface, :cpp:`llama::VirtualRecord` can integrate with these using the :cpp:`load()`, :cpp:`loadAs<T>()` and :cpp:`store(T)` functions.
Additionally, if the user already has types supporting the C++ tuple interface, :cpp:`llama::RecordRef` can integrate with these using the :cpp:`load()`, :cpp:`loadAs<T>()` and :cpp:`store(T)` functions.

.. code-block:: C++

Expand All @@ -230,22 +230,22 @@ Additionally, if the user already has types supporting the C++ tuple interface,
p1.alpha = 255;
record.store(p1); // tuple-element-wise assignment from p1 to record.asFlatTuple()

Keep in mind that the load and store functionality always reads/writes all elements referred to by a :cpp:`llama::VirtualRecord`.
Keep in mind that the load and store functionality always reads/writes all elements referred to by a :cpp:`llama::RecordRef`.


Structured bindings
-------------------

WARNING: This is an experimental feature and might completely change in the future.

A :cpp:`llama::VirtualRecord` implements the C++ tuple interface itself to allow destructuring:
A :cpp:`llama::RecordRef` implements the C++ tuple interface itself to allow destructuring:

.. code-block:: C++

auto record = view(1, 2, 3);
auto [color, a] = record; // color is another VirtualRecord, a is a char&, 1 call to mapping function
auto [color, a] = record; // color is another RecordRef, a is a char&, 1 call to mapping function
auto [r, g, b] = color; // r, g, b are float&, 3 calls to mapping function

Contrary to destructuring a tuple generated by calling :cpp:`asTuple()` or :cpp:`asFlatTuple()`,
the mapping function is not invoked for other instances of :cpp:`llama::VirtualRecord` created during the destructuring.
the mapping function is not invoked for other instances of :cpp:`llama::RecordRef` created during the destructuring.
The mapping function is just invoked to form references for terminal accesses.
2 changes: 1 addition & 1 deletion docs/pages/views.rst
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ Alternatively, an addressing with integral record coordinates is possible like t
These record coordinates are zero-based, nested indices reflecting the nested tuple-like structure of the record dimension.

Notice that the :cpp:`operator()` is invoked twice in the last example and that an intermediate object is needed for this to work.
This object is a :cpp:`llama::VirtualRecord`.
This object is a :cpp:`llama::RecordRef`.

.. _label-virtualview:

Expand Down
4 changes: 2 additions & 2 deletions examples/alpaka/nbody/nbody.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,8 @@ struct VecType<1>
using type = FP;
};

template<int Elems, typename ViewParticleI, typename VirtualParticleJ>
LLAMA_FN_HOST_ACC_INLINE void pPInteraction(ViewParticleI pi, VirtualParticleJ pj)
template<int Elems, typename ViewParticleI, typename ParticleRefJ>
LLAMA_FN_HOST_ACC_INLINE void pPInteraction(ViewParticleI pi, ParticleRefJ pj)
{
using Vec = typename VecType<Elems>::type;

Expand Down
12 changes: 6 additions & 6 deletions examples/alpaka/pic/pic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -380,8 +380,8 @@ LLAMA_FN_HOST_ACC_INLINE auto cross(const Vec3F& a, const Vec3F& b)
a(Z{}) * b(Y{}) - a(Y{}) * b(Z{}));
}

template<typename VirtualParticle, typename FieldView>
LLAMA_FN_HOST_ACC_INLINE void advance_particle(VirtualParticle part, const FieldView& E, const FieldView& B)
template<typename ParticleRef, typename FieldView>
LLAMA_FN_HOST_ACC_INLINE void advance_particle(ParticleRef part, const FieldView& E, const FieldView& B)
{
/* Interpolate fields (nearest-neighbor) */
const auto i = static_cast<size_t>(part(R{}, X{}) * inv_dx);
Expand Down Expand Up @@ -417,8 +417,8 @@ LLAMA_FN_HOST_ACC_INLINE void advance_particle(VirtualParticle part, const Field
#endif
}

template<typename VirtualParticle>
LLAMA_FN_HOST_ACC_INLINE void particle_boundary_conditions(VirtualParticle p)
template<typename ParticleRef>
LLAMA_FN_HOST_ACC_INLINE void particle_boundary_conditions(ParticleRef p)
{
//* Periodic boundary condition
if(p(R{}, X{}) < dx)
Expand All @@ -431,8 +431,8 @@ LLAMA_FN_HOST_ACC_INLINE void particle_boundary_conditions(VirtualParticle p)
p(R{}, Y{}) -= (Y_ - 3) * dx;
}

template<typename VirtualParticle, typename FieldView>
LLAMA_FN_HOST_ACC_INLINE void deposit_current(const VirtualParticle& part, FieldView& J)
template<typename ParticleRef, typename FieldView>
LLAMA_FN_HOST_ACC_INLINE void deposit_current(const ParticleRef& part, FieldView& J)
{
/* Calculation of previous position */
const Real igamma = 1 / sqrt(1 + squaredNorm(part(U{})));
Expand Down
4 changes: 2 additions & 2 deletions examples/cuda/nbody/nbody.cu
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ using ParticleJ = llama::Record<
// using SharedMemoryParticle = Particle;
using SharedMemoryParticle = ParticleJ;

template<typename VirtualParticleI, typename VirtualParticleJ>
__device__ void pPInteraction(VirtualParticleI&& pi, VirtualParticleJ pj)
template<typename ParticleRefI, typename ParticleRefJ>
__device__ void pPInteraction(ParticleRefI&& pi, ParticleRefJ pj)
{
auto dist = pi(tag::Pos()) - pj(tag::Pos());
dist *= dist;
Expand Down
4 changes: 2 additions & 2 deletions examples/nbody/nbody.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ namespace usellama
>;
// clang-format on

template<typename VirtualParticleI, typename VirtualParticleJ>
LLAMA_FN_HOST_ACC_INLINE void pPInteraction(VirtualParticleI& pi, VirtualParticleJ pj)
template<typename ParticleRefI, typename ParticleRefJ>
LLAMA_FN_HOST_ACC_INLINE void pPInteraction(ParticleRefI& pi, ParticleRefJ pj)
{
auto dist = pi(tag::Pos{}) - pj(tag::Pos{});
dist *= dist;
Expand Down
4 changes: 2 additions & 2 deletions examples/nbody_benchmark/nbody.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ using Particle = llama::Record<
>;
// clang-format on

template<typename VirtualParticle>
LLAMA_FN_HOST_ACC_INLINE void pPInteraction(VirtualParticle p1, VirtualParticle p2)
template<typename ParticleRef>
LLAMA_FN_HOST_ACC_INLINE void pPInteraction(ParticleRef p1, ParticleRef p2)
{
auto dist = p1(tag::Pos{}) - p2(tag::Pos{});
dist *= dist;
Expand Down
Loading