Basic Types¶
HighFM currently offers the following types:
Template Parameters:¶
All types share the same template parameters:
template<Number ElemType, DataLocation Location, template<typename, typename> typename Storage>
class Vector;
where ElemType
is the data type of entries in the container (double
or float
), Location
determines where the data is located (i.e, on the Host
or on the Device
) and the Storage
indicates the container used for storing the object in memory. Currently, HighFM supports two Storage
types: Array and DataMap.
Array represents a plain contiguous array that has its memory allocation automatically managed by the HighFM library. This allows the size of the container (and the underlying memory allocation) to be changed at will, similarly to the std::vector
from the STL. It is recommended to use this container when constructing new types.
Note
The resize()
method is destructive (i.e., all previous content will be clear when resizing the container).
DataMap, on the other hand, represent a map to an existing memory allocation, essentially, wrapping a pointer and its size as a HighFM container. Since the memory allocation is managed externally, the size of the container is fixed. The DataMap can be remapped to another container using the map_to()
method. This storage type should be used for either wrapping data generated by external libraries or manipulating data slices.
For example, Vector<float, Host, Array>
indicates a dense vector of float
entries that is located in the Host
and uses the Array container for storing the data. In this case, you can just write Vector<float>
as the default Location
is the Host
and the default Storage
is the Array
. The other types follow the same rules.
Capacity:¶
The number of rows and columns for any vector or matrix can be retrieved by calling the
rows()
andcols()
methods, respectively.The
size()
routine returns either the number of entries when working with dense objects or the number of nonzero elements when working with sparse objects.
Element Access and Slicing:¶
Individual entries in the container can be accessed using the operators
[]
and()
.Most containers also support slicing, i.e., creating a map to some part of the matrix or vector. This is typically achieved by specifying a
Range
or using thekAll
tag. TheRange
object has the following structure:
-
struct Range¶
A (contiguous) range of entries in the container.
Note that you can construct the Range
object in place, e.g., vec({2, 6})
constructs a slice that spans the entries 2
to 6
of the vector vec
.
Assignment:¶
All data types support the assignment operator
=
to copy data between two objects. This operator is also used for converting from sparse to dense vectors/matrices as well as for evaluating BLAS/LAPACK expressions.If the source container is located in the
host
and the destination, in thedevice
, or vice-versa, this will imply a data transfer between the two memory spaces.There is no
move
assignment or constructor for the DataMap. Let us consider the following code
MatrixMap<double> mat1;
Matrix<double> mat2;
mat1 = mat2({0, 5}, {0, 5})
If the move
assignment operator is specified, then submatrix mat2({0, 5}, {0, 5})
will be moved to the mat1
, replacing its memory allocation. However, in this case, we expect the data to be copied from one matrix to another. To avoid this ambiguity, we reserve the = operator exclusively for copying data when dealing with slices and DataMap. The Array does not have this restriction.
Compatibility¶
To have maximum compatibility with other libraries, all HighFM objects can be reduced to a simple, compact struct that only contains the pointer to the beginning of the container as well as additional information related to the object (e.g., number of rows, number of columns, leading dimension, etc.). For instance, the struct associated with a Matrix is
-
template<typename T>
struct MatrixData A simple struct storing the data of a dense matrix in the column-major format.
To retrieve the compact struct from an existing object obj
, you can call the obj.matrix_data()
method. Note that, besides changing the values within the container, any modification to a member of the struct will not be reflected in the original object (e.g., changing the number of rows or columns). The compact struct can also be used for constructing new HighFM objects.