#include <FWCore/Utilities/interface/SoATuple.h>
Description: Structure of Arrays Tuple
Usage: Often we want to group data which are related to one item and then group related items. This is often done by making a structure,Foo, to hold the data related to one item and then place the structure into a container (e.g. std::vector<Foo>). This is referred to as an 'Array of Structures'. However, this grouping can be inefficient if not all of the data about one item are used at the same time. So to access one data for one item will cause the CPU to retrieve nearby memory which is then not used. If the code is looking at the same data for multiple items this will lead to many data cache misses in the CPU.
A different grouping is to place the first data element for all items into one array, the second data element for all items into a second array, then so on. This is referred to as a 'Structure of Arrays'.
This class will take an arbitrary number of template arguments and it will group data of that argument type together in memory.
Example: Data about one item is represented by a double, int and bool
One can then push data into the collection. You must insert all data for each item.
s.push_back(std::make_tuple(double{3.14},int{5},false)); s.emplace_back(double{90.},int{0},true);
It is best if you call 'reserve' before pushing or emplacing items into the container in order to minimize memory allocations.
You get the data out by specify the 'ordinal' of the data element as well as the index
double v = s.get<0>(1); //this return 90. \encode It is possible to loop over a data element for all items in the collection \code for(auto it = s.begin<1>(), itEnd=s.end<1>(); it != itEnd; ++it) { std::cout<<*it<<" "; } //This returns '5 0 ' \encode This template arguments for this class are not limited to simple builtins, any type can be used: \code edm::SoATuple<std::string, ThreeVector> sComplex;
To help keep track of the purpose of the template arguments, we suggest using an enum to denote each one:
enum {kPx,kPy,kPz}; edm::SoATuple<double,double,double> s3Vecs; ... if(s.3Vecs.get<kPx>(i) > s.3Vecs.get<kPy>(i)) { ... }
A non-default alignment for a stored type can be specified by using the edm::Aligned<T,I> where I is an unsigned int value denoting the requested byte alignment. There is also a specialized version, edm::AlignedVec which has the proper alignment for SSE operations (16 byte aligned).
edm::SoATuple<edm::Aligned<float,16>,edm::Aligned<float,16>,edm::Aligned<float,16>> vFloats;
which is equivalent to
edm::SoATuple<edm::AlignedVec<float>,edm::AlignedVec<float>,edm::AlignedVec<float>> vFloats;
Explicitly aligned types and defaultly aligned types can be freely mixed in any order within the template arguments.