Class DArray represents a distributed array. More...
#include <darray.h>
Public Member Functions | |
DArray () | |
Default constructor. | |
DArray (int size, Distribution d=DIST) | |
Creates an empty distributed array. More... | |
DArray (int size, const T &initial_value, Distribution d=DIST) | |
Creates a distributed array with size elements equal to initial_value. More... | |
DArray (int size, T *const initial_array, Distribution d=DIST) | |
Creates a distributed array with size elements. Elements are copied from initial_array. Note that the length of initial_array must equal size. More... | |
DArray (int size, T(*f)(int), Distribution d=DIST) | |
Creates a distributed array with size elements. Initializes all elements via the given function f. Note that global indices are pass to this function as arguments. More... | |
template<typename F > | |
DArray (int size, const F &f, Distribution d=DIST) | |
Creates a distributed array with size elements. Initializes all elements via the given functor f. Note that global indices are pass to this functor as arguments. More... | |
DArray (const DArray< T > &cs) | |
Copy constructor. More... | |
~DArray () | |
Destructor. | |
DArray< T > & | operator= (const DArray< T > &rhs) |
Assignment operator. More... | |
void | fill (const T &value) |
Initializes the elements of the distributed array with the value value. More... | |
void | fill (T *const values) |
Initializes the elements of the distributed array with the elements of the given array of values. Note that the length of values must match the size of the distributed array (not checked). More... | |
void | fill (T(*f)(int)) |
Initializes the elements of the distributed array via the given function f. Note that global indices are pass to this function as arguments. More... | |
template<typename F > | |
void | fill (const F &f) |
Initializes the elements of the distributed array via the given functor f. Note that global indices are pass to this functor as arguments. More... | |
template<typename MapFunctor > | |
void | mapInPlace (MapFunctor &f) |
Replaces each element a[i] of the distributed array with f(a[i]). More... | |
template<typename MapIndexFunctor > | |
void | mapIndexInPlace (MapIndexFunctor &f) |
Replaces each element a[i] of the distributed array with f(i, a[i]). Note that besides the element itself also its index is passed to the functor. More... | |
template<typename R , typename MapFunctor > | |
msl::DArray< R > | map (MapFunctor &f) |
Returns a new distributed array with a_new[i] = f(a[i]). More... | |
template<typename R , typename MapIndexFunctor > | |
DArray< R > | mapIndex (MapIndexFunctor &f) |
Returns a new distributed array with a_new[i] = f(i, a[i]). Note that besides the element itself also its index is passed to the functor. More... | |
template<typename MapStencilFunctor > | |
void | mapStencilInPlace (MapStencilFunctor &f, T neutral_value) |
Replaces each element a[i] of the distributed array with f(i, a). Note that the index i and the local partition is passed to the functor. More... | |
template<typename R , typename MapStencilFunctor > | |
DArray< R > | mapStencil (MapStencilFunctor &f, T neutral_value) |
Non-inplace variant of the mapStencil skeleton. More... | |
template<typename F > | |
void | mapInPlace (const msl::Fct1< T, T, F > &f) |
Replaces each element a[i] of the distributed array with f(a[i]). Note that this is a CPU only skeleton. More... | |
void | mapInPlace (T(*f)(T)) |
Replaces each element a[i] of the distributed array with f(a[i]). Note that this is a CPU only skeleton. More... | |
template<typename F > | |
void | mapIndexInPlace (const msl::Fct2< int, T, T, F > &f) |
Replaces each element a[i] of the distributed array with f(i, a[i]). Note that besides the element itself also its index is passed to the functor. Also note that this is a CPU only skeleton. More... | |
void | mapIndexInPlace (T(*f)(int, T)) |
Replaces each element a[i] of the distributed array with f(i, a[i]). Note that besides the element itself also its index is passed to the functor. Also note that this is a CPU only skeleton. More... | |
template<typename R , typename F > | |
msl::DArray< R > | map (const msl::Fct1< T, R, F > &f) |
Non-inplace variant of the map skeleton. Note that this is a CPU only skeleton. More... | |
template<typename R > | |
msl::DArray< R > | map (R(*f)(T)) |
Non-inplace variant of the map skeleton. Note that this is a CPU only skeleton. More... | |
template<typename R , typename F > | |
DArray< R > | mapIndex (const msl::Fct2< int, T, R, F > &f) |
Non-inplace variant of the mapIndex skeleton. Note that this is a CPU only skeleton. More... | |
template<typename R > | |
DArray< R > | mapIndex (R(*f)(int, T)) |
Non-inplace variant of the mapIndex skeleton. Note that this is a CPU only skeleton. More... | |
template<typename T2 , typename ZipFunctor > | |
void | zipInPlace (DArray< T2 > &b, ZipFunctor &f) |
Replaces each element a[i] of the distributed array with f(a[i], b[i]) with b being another distributed array of the same size. More... | |
template<typename T2 , typename ZipIndexFunctor > | |
void | zipIndexInPlace (DArray< T2 > &b, ZipIndexFunctor &f) |
Replaces each element a[i] of the distributed array with f(i, a[i], b[i]). Note that besides the elements themselves also the index is passed to the functor. More... | |
template<typename R , typename T2 , typename ZipFunctor > | |
DArray< R > | zip (DArray< T2 > &b, ZipFunctor &f) |
Non-inplace variant of the zip skeleton. More... | |
template<typename R , typename T2 , typename ZipIndexFunctor > | |
DArray< R > | zipIndex (DArray< T2 > &b, ZipIndexFunctor &f) |
Non-inplace variant of the zipIndex skeleton. More... | |
template<typename T2 , typename F > | |
void | zipInPlace (DArray< T2 > &b, const Fct2< T, T2, T, F > &f) |
Replaces each element a[i] of the distributed array with f(a[i], b[i]) with b being another distributed array of the same size. Note that this is a CPU only skeleton. More... | |
template<typename T2 > | |
void | zipInPlace (DArray< T2 > &b, T(*f)(T, T2)) |
Replaces each element a[i] of the distributed array with f(a[i], b[i]) with b being another distributed array of the same size. Note that this is a CPU only skeleton. More... | |
template<typename T2 , typename F > | |
void | zipIndexInPlace (DArray< T2 > &b, const Fct3< int, T, T2, T, F > &f) |
Replaces each element a[i] of the distributed array with f(i, a[i], b[i]). Note that besides the elements themselves also the index is passed to the functor. Note that this is a CPU only skeleton. More... | |
template<typename T2 > | |
void | zipIndexInPlace (DArray< T2 > &b, T(*f)(int, T, T2)) |
Replaces each element a[i] of the distributed array with f(i, a[i], b[i]). Note that besides the elements themselves also the index is passed to the functor. Note that this is a CPU only skeleton. More... | |
template<typename R , typename T2 , typename F > | |
DArray< R > | zip (DArray< T2 > &b, const Fct2< T, T2, R, F > &f) |
Non-inplace variant of the zip skeleton. Note that this is a CPU only skeleton. More... | |
template<typename R , typename T2 > | |
DArray< R > | zip (DArray< T2 > &b, R(*f)(T, T2)) |
Non-inplace variant of the zip skeleton. Note that this is a CPU only skeleton. More... | |
template<typename R , typename T2 , typename F > | |
DArray< R > | zipIndex (DArray< T2 > &b, const Fct3< int, T, T2, R, F > &f) |
Non-inplace variant of the zipIndex skeleton. Note that this is a CPU only skeleton. More... | |
template<typename R , typename T2 > | |
DArray< R > | zipIndex (DArray< T2 > &b, R(*f)(int, T, T2)) |
Non-inplace variant of the zipIndex skeleton. Note that this is a CPU only skeleton. More... | |
template<typename FoldFunctor > | |
T | fold (FoldFunctor &f, bool final_fold_on_cpu=1) |
Reduces all elements of the distributed array to a single element by successively applying the given functor f. Note that f needs to be a commutative function. Note that this is a CPU only skeleton. More... | |
template<typename F > | |
T | fold (const Fct2< T, T, T, F > &f) |
Reduces all elements of the distributed array to a single element by successively applying the given functor f. Note that f needs to be a commutative function. Note that this is a CPU only skeleton. More... | |
T | fold (T(*f)(T, T)) |
Reduces all elements of the distributed array to a single element by successively applying the given function f. Note that f needs to be a commutative function. Note that this is a CPU only skeleton. More... | |
void | broadcastPartition (int partitionIndex) |
Broadcasts the partition with index partitionIndex to all processes. Afterwards, each partition of the distributed array stores the same values. Note that 0 <= partitionIndex <= size/numProcesses. More... | |
void | gather (T *b) |
Transforms a distributed array to an ordinary array by copying each element to the given array b. b must at least be of length size. More... | |
void | gather (msl::DArray< T > &da) |
Transforms a distributed array to a copy distributed distributed array by copying each element to the given distributed array da. da must be copy distributed, otherwise this function immediately returns. More... | |
template<class F > | |
void | permutePartition (const Fct1< int, int, F > &f) |
Permutes the partitions of the distributed array according to the given function f. f must be bijective and return the ID of the new process p_i to store the partition, with 0 <= i < np. More... | |
void | permutePartition (int(*f)(int)) |
Permutes the partitions of the distributed array according to the given function f. f must be bijective and return the the ID of the new process p_i to store the partition, with 0 <= i < np. More... | |
T * | getLocalPartition () const |
Returns the local partition. More... | |
T | get (int index) const |
Returns the element at the given global index index. More... | |
void | set (int globalIndex, const T &v) |
Sets the element at the given global index globalIndex to the given value v, with 0 <= globalIndex < size. More... | |
int | getSize () const |
Returns the global size of the distributed array. More... | |
int | getLocalSize () const |
Returns the size of local partitions of the distributed array. More... | |
int | getFirstIndex () const |
Returns the first (global) index of the local partition. More... | |
bool | isLocal (int index) const |
Checks whether the element at the given global index index is locally stored. More... | |
T | getLocal (int localIndex) const |
Returns the element at the given local index index. Note that 0 <= index < getLocalSize() must hold (will not be checked, for reasons of performance). More... | |
void | setLocal (int localIndex, const T &v) |
Sets the element at the given local index localIndex to the given value v. More... | |
std::vector< GPUExecutionPlan < T > > | getExecPlans () |
Returns the GPU execution plans that store information about size, etc. for the GPU partitions. For internal purposes. More... | |
void | setCopyDistribution () |
Switch the distribution scheme from distributed to copy distributed. | |
void | setDistribution () |
Switch the distribution scheme from copy distributed to distributed. | |
std::vector< T * > | upload (bool allocOnly=0) |
Manually upload the local partition to GPU memory. More... | |
void | download () |
Manually download the local partition from GPU memory. | |
void | freeDevice () |
Manually free device memory. | |
void | setGpuDistribution (Distribution dist) |
Set how the local partition is distributed among the GPUs. Current distribution schemes are: distributed, copy distributed. More... | |
Distribution | getGpuDistribution () |
Returns the current GPU distribution scheme. More... | |
void | show (const std::string &descr=std::string()) |
Prints the distributed array to standard output. Optionally, the user may pass a description that will be printed with the output. More... | |
void | printLocal () |
Each process prints its local partition of the distributed array. | |
Class DArray represents a distributed array.
A distributed array represents a one-dimensional parallel container and is distributed among all MPI processes the application was started with. It includes data parallel skeletons such as map, mapStencil, zip, and fold as well as variants of these skeletons.
T | Element type. Restricted to classes without pointer data members. |
msl::DArray< T >::DArray | ( | int | size, |
Distribution | d = DIST |
||
) |
Creates an empty distributed array.
size | Size of the distributed array. |
d | Distribution of the distributed array. |
msl::DArray< T >::DArray | ( | int | size, |
const T & | initial_value, | ||
Distribution | d = DIST |
||
) |
Creates a distributed array with size elements equal to initial_value.
size | Size of the distributed array. |
initial_value | Initial value for all elements. |
d | Distribution of the distributed array. |
msl::DArray< T >::DArray | ( | int | size, |
T *const | initial_array, | ||
Distribution | d = DIST |
||
) |
Creates a distributed array with size elements. Elements are copied from initial_array. Note that the length of initial_array must equal size.
size | Size of the distributed array. |
initial_array | Initial array to copy elements from. |
d | Distribution of the distributed array. |
msl::DArray< T >::DArray | ( | int | size, |
T(*)(int) | f, | ||
Distribution | d = DIST |
||
) |
Creates a distributed array with size elements. Initializes all elements via the given function f. Note that global indices are pass to this function as arguments.
size | Size of the distributed array. |
f | Function to initialize the elements of the distributed array. |
d | Distribution of the distributed array. |
msl::DArray< T >::DArray | ( | int | size, |
const F & | f, | ||
Distribution | d = DIST |
||
) |
Creates a distributed array with size elements. Initializes all elements via the given functor f. Note that global indices are pass to this functor as arguments.
size | Size of the distributed array. |
f | Functor to initialize the elements of the distributed array. |
d | Distribution of the distributed array. |
msl::DArray< T >::DArray | ( | const DArray< T > & | cs | ) |
Copy constructor.
cs | The copy source. |
void msl::DArray< T >::broadcastPartition | ( | int | partitionIndex | ) |
Broadcasts the partition with index partitionIndex to all processes. Afterwards, each partition of the distributed array stores the same values. Note that 0 <= partitionIndex <= size/numProcesses.
partitionIndex | The index of the partition to broadcast. |
void msl::DArray< T >::fill | ( | const T & | value | ) |
Initializes the elements of the distributed array with the value value.
value | The value. |
void msl::DArray< T >::fill | ( | T *const | values | ) |
Initializes the elements of the distributed array with the elements of the given array of values. Note that the length of values must match the size of the distributed array (not checked).
values | The array of values. |
void msl::DArray< T >::fill | ( | T(*)(int) | f | ) |
Initializes the elements of the distributed array via the given function f. Note that global indices are pass to this function as arguments.
f | The initializer function. |
Initializes the elements of the distributed array via the given functor f. Note that global indices are pass to this functor as arguments.
f | The initializer functor. |
T msl::DArray< T >::fold | ( | FoldFunctor & | f, |
bool | final_fold_on_cpu = 1 |
||
) |
Reduces all elements of the distributed array to a single element by successively applying the given functor f. Note that f needs to be a commutative function. Note that this is a CPU only skeleton.
f | The fold functor, must be of type AFoldFunctor. |
final_fold_on_cpu | Specifies whether the final fold steps are done by the CPU. Default is true and since this is the CPU version of this skeleton, passing false will have no effect. |
Reduces all elements of the distributed array to a single element by successively applying the given functor f. Note that f needs to be a commutative function. Note that this is a CPU only skeleton.
f | The fold functor, must be a 'curried' function pointer. |
T msl::DArray< T >::fold | ( | T(*)(T, T) | f | ) |
Reduces all elements of the distributed array to a single element by successively applying the given function f. Note that f needs to be a commutative function. Note that this is a CPU only skeleton.
f | The fold function. |
void msl::DArray< T >::gather | ( | T * | b | ) |
Transforms a distributed array to an ordinary array by copying each element to the given array b. b must at least be of length size.
b | The array to store the elements of the distributed array. |
void msl::DArray< T >::gather | ( | msl::DArray< T > & | da | ) |
Transforms a distributed array to a copy distributed distributed array by copying each element to the given distributed array da. da must be copy distributed, otherwise this function immediately returns.
da | The (copy distributed) distributed array to stores the elements of the distributed array. |
T msl::DArray< T >::get | ( | int | index | ) | const |
Returns the element at the given global index index.
index | The global index. |
std::vector<GPUExecutionPlan<T> > msl::DArray< T >::getExecPlans | ( | ) |
Returns the GPU execution plans that store information about size, etc. for the GPU partitions. For internal purposes.
int msl::DArray< T >::getFirstIndex | ( | ) | const |
Returns the first (global) index of the local partition.
Distribution msl::DArray< T >::getGpuDistribution | ( | ) |
Returns the current GPU distribution scheme.
T msl::DArray< T >::getLocal | ( | int | localIndex | ) | const |
Returns the element at the given local index index. Note that 0 <= index < getLocalSize() must hold (will not be checked, for reasons of performance).
index | The local index. |
T* msl::DArray< T >::getLocalPartition | ( | ) | const |
Returns the local partition.
int msl::DArray< T >::getLocalSize | ( | ) | const |
Returns the size of local partitions of the distributed array.
int msl::DArray< T >::getSize | ( | ) | const |
Returns the global size of the distributed array.
bool msl::DArray< T >::isLocal | ( | int | index | ) | const |
Checks whether the element at the given global index index is locally stored.
index | The global index. |
msl::DArray<R> msl::DArray< T >::map | ( | MapFunctor & | f | ) |
Returns a new distributed array with a_new[i] = f(a[i]).
f | The map functor, must be of type AMapFunctor. |
msl::DArray<R> msl::DArray< T >::map | ( | const msl::Fct1< T, R, F > & | f | ) |
Non-inplace variant of the map skeleton. Note that this is a CPU only skeleton.
f | The map functor, must be a 'curried' function pointer. |
Non-inplace variant of the map skeleton. Note that this is a CPU only skeleton.
f | The map function. |
DArray<R> msl::DArray< T >::mapIndex | ( | MapIndexFunctor & | f | ) |
Returns a new distributed array with a_new[i] = f(i, a[i]). Note that besides the element itself also its index is passed to the functor.
f | The mapIndex functor, must be of type AMapIndexFunctor. |
DArray<R> msl::DArray< T >::mapIndex | ( | const msl::Fct2< int, T, R, F > & | f | ) |
Non-inplace variant of the mapIndex skeleton. Note that this is a CPU only skeleton.
f | The mapIndex functor, must be a 'curried' function pointer. |
Non-inplace variant of the mapIndex skeleton. Note that this is a CPU only skeleton.
f | The mapIndex function. |
void msl::DArray< T >::mapIndexInPlace | ( | MapIndexFunctor & | f | ) |
Replaces each element a[i] of the distributed array with f(i, a[i]). Note that besides the element itself also its index is passed to the functor.
f | The mapIndex functor, must be of type AMapIndexFunctor. |
void msl::DArray< T >::mapIndexInPlace | ( | const msl::Fct2< int, T, T, F > & | f | ) |
Replaces each element a[i] of the distributed array with f(i, a[i]). Note that besides the element itself also its index is passed to the functor. Also note that this is a CPU only skeleton.
f | The mapIndex functor, must be a 'curried' function pointer. |
void msl::DArray< T >::mapIndexInPlace | ( | T(*)(int, T) | f | ) |
Replaces each element a[i] of the distributed array with f(i, a[i]). Note that besides the element itself also its index is passed to the functor. Also note that this is a CPU only skeleton.
f | The mapIndex function. |
void msl::DArray< T >::mapInPlace | ( | MapFunctor & | f | ) |
Replaces each element a[i] of the distributed array with f(a[i]).
f | The map functor, must be of type AMapFunctor. |
void msl::DArray< T >::mapInPlace | ( | const msl::Fct1< T, T, F > & | f | ) |
Replaces each element a[i] of the distributed array with f(a[i]). Note that this is a CPU only skeleton.
f | The map functor, must be a 'curried' function pointer. |
void msl::DArray< T >::mapInPlace | ( | T(*)(T) | f | ) |
Replaces each element a[i] of the distributed array with f(a[i]). Note that this is a CPU only skeleton.
f | The mapIndex function. |
DArray<R> msl::DArray< T >::mapStencil | ( | MapStencilFunctor & | f, |
T | neutral_value | ||
) |
Non-inplace variant of the mapStencil skeleton.
f | The mapStencil functor, must be of type AMapStencilFunctor. |
void msl::DArray< T >::mapStencilInPlace | ( | MapStencilFunctor & | f, |
T | neutral_value | ||
) |
Replaces each element a[i] of the distributed array with f(i, a). Note that the index i and the local partition is passed to the functor.
f | The mapStencil functor, must be of type AMapStencilFunctor. |
DArray<T>& msl::DArray< T >::operator= | ( | const DArray< T > & | rhs | ) |
Assignment operator.
rhs | Right hand side of assignment operator. |
|
inline |
Permutes the partitions of the distributed array according to the given function f. f must be bijective and return the ID of the new process p_i to store the partition, with 0 <= i < np.
f | The bijective function, must be a curried function pointer. |
|
inline |
Permutes the partitions of the distributed array according to the given function f. f must be bijective and return the the ID of the new process p_i to store the partition, with 0 <= i < np.
f | The bijective function. |
void msl::DArray< T >::set | ( | int | globalIndex, |
const T & | v | ||
) |
Sets the element at the given global index globalIndex to the given value v, with 0 <= globalIndex < size.
globalIndex | The global index. |
v | The new value. |
void msl::DArray< T >::setGpuDistribution | ( | Distribution | dist | ) |
Set how the local partition is distributed among the GPUs. Current distribution schemes are: distributed, copy distributed.
dist | The GPU distribution scheme. |
void msl::DArray< T >::setLocal | ( | int | localIndex, |
const T & | v | ||
) |
Sets the element at the given local index localIndex to the given value v.
localIndex | The local index. |
v | The new value. |
void msl::DArray< T >::show | ( | const std::string & | descr = std::string() | ) |
Prints the distributed array to standard output. Optionally, the user may pass a description that will be printed with the output.
descr | The description string. |
std::vector<T*> msl::DArray< T >::upload | ( | bool | allocOnly = 0 | ) |
Manually upload the local partition to GPU memory.
allocOnly | Specifies whether data is actually uploaded. |
DArray<R> msl::DArray< T >::zip | ( | DArray< T2 > & | b, |
ZipFunctor & | f | ||
) |
Non-inplace variant of the zip skeleton.
f | The zip functor, must be of type AZipFunctor. |
DArray<R> msl::DArray< T >::zip | ( | DArray< T2 > & | b, |
const Fct2< T, T2, R, F > & | f | ||
) |
Non-inplace variant of the zip skeleton. Note that this is a CPU only skeleton.
f | The zip functor, must be a 'curried' function pointer. |
DArray<R> msl::DArray< T >::zip | ( | DArray< T2 > & | b, |
R(*)(T, T2) | f | ||
) |
Non-inplace variant of the zip skeleton. Note that this is a CPU only skeleton.
f | The zip function. |
DArray<R> msl::DArray< T >::zipIndex | ( | DArray< T2 > & | b, |
ZipIndexFunctor & | f | ||
) |
Non-inplace variant of the zipIndex skeleton.
f | The zipIndex functor, must be of type AZipIndexFunctor. |
DArray<R> msl::DArray< T >::zipIndex | ( | DArray< T2 > & | b, |
const Fct3< int, T, T2, R, F > & | f | ||
) |
Non-inplace variant of the zipIndex skeleton. Note that this is a CPU only skeleton.
f | The zipIndex functor, must be a 'curried' function pointer. |
DArray<R> msl::DArray< T >::zipIndex | ( | DArray< T2 > & | b, |
R(*)(int, T, T2) | f | ||
) |
Non-inplace variant of the zipIndex skeleton. Note that this is a CPU only skeleton.
f | The zipIndex function. |
void msl::DArray< T >::zipIndexInPlace | ( | DArray< T2 > & | b, |
ZipIndexFunctor & | f | ||
) |
Replaces each element a[i] of the distributed array with f(i, a[i], b[i]). Note that besides the elements themselves also the index is passed to the functor.
f | The zipIndex functor, must be of type AZipIndexFunctor. |
void msl::DArray< T >::zipIndexInPlace | ( | DArray< T2 > & | b, |
const Fct3< int, T, T2, T, F > & | f | ||
) |
Replaces each element a[i] of the distributed array with f(i, a[i], b[i]). Note that besides the elements themselves also the index is passed to the functor. Note that this is a CPU only skeleton.
f | The zipIndex functor, must be a 'curried' function pointer. |
void msl::DArray< T >::zipIndexInPlace | ( | DArray< T2 > & | b, |
T(*)(int, T, T2) | f | ||
) |
Replaces each element a[i] of the distributed array with f(i, a[i], b[i]). Note that besides the elements themselves also the index is passed to the functor. Note that this is a CPU only skeleton.
f | The zipIndex function. |
void msl::DArray< T >::zipInPlace | ( | DArray< T2 > & | b, |
ZipFunctor & | f | ||
) |
Replaces each element a[i] of the distributed array with f(a[i], b[i]) with b being another distributed array of the same size.
f | The zip functor, must be of type AZipFunctor. |
void msl::DArray< T >::zipInPlace | ( | DArray< T2 > & | b, |
const Fct2< T, T2, T, F > & | f | ||
) |
Replaces each element a[i] of the distributed array with f(a[i], b[i]) with b being another distributed array of the same size. Note that this is a CPU only skeleton.
f | The zip functor, must be a 'curried' function pointer. |
void msl::DArray< T >::zipInPlace | ( | DArray< T2 > & | b, |
T(*)(T, T2) | f | ||
) |
Replaces each element a[i] of the distributed array with f(a[i], b[i]) with b being another distributed array of the same size. Note that this is a CPU only skeleton.
f | The zip function. |