|
DIY
3.0
data-parallel out-of-core C++ library
|
The following is an example of the steps needed to initialize diy:
The block is the basic unit of everything (data, decomposition, communication) in diy. Use it to define your data model and any state associated with the data that will be needed to accompany the data throughout its lifetime. In addition to the data in the block, it should define functions to create and destroy the block that diy can call. If the blocks are intended to be moved in and out of core, then the block must also define save and load functions.
There are 2 common ways to set up the block.
AddBlock is a functor that gets and stores any custom arguments and overloads the function call with access to the custom arguments:Define your global data bounds, the MPI communicator, and the file storage object (if blocks will be moved in and out of core). Then define the diy Master object. The Master manages loading/saving blocks, executing their callback functions, and exchanging data between them. If the block long form (with AddBlock functor) is used, define the AddBlock object as well.
When all blocks will remain in memory, there is a shorter form of the Master constructor that can be used. In this case there is no need to specify most of the arguments because they relate to block loading/unloading.
Blocks can be assigned to processes contiguously or in round-robin fashion:
Any custom decomposition can be formed by assigning links (communication neighborhoods of blocks) manually. However, for a regular grid of blocks, diy provides a regular decomposition of blocks with either continuous (floating-point extents that share common boundaries) or discrete (integer extents that may or may not overlap) bounds.
Diy offers two versions of a decompose function, depending on whether the short or long form of the block is used. Recall that the long form has an AddBlock functor, while the short form does not. In the short form, one of the arguments to decompose is master, and in the long form, provide addblock instead:
Strictly speaking, the second (long form) decomposition does not require an entire AddBlock object, as long as the block create function has the same signature as AddBlock. That pattern is:
decompose is actually a convenience function that creates a RegularDecomposer object, calls its decompose method, and then destroys the RegularDecomposer. The user may want persistent access to RegularDecomposer because it offers useful information about the decomposition (block bounds, numbers of blocks in each dimension, and so forth.). In that case, we suggest defining RegularDecomposer and calling its decompose function yourself:
Here is one version of each of the above options combined into a complete program. This example uses the short form of blocks:
Below is one more complete example, this time using the long form of the block:
Documentation about the Master object appears below. The RegularDecomposer is documented in the Decomposition page.
Functions | |
| diy::Master::Master (mpi::communicator comm, int threads=1, int limit=-1, CreateBlock create=0, DestroyBlock destroy=0, ExternalStorage *storage=0, SaveBlock save=0, LoadBlock load=0, QueuePolicy *q_policy=new QueueSizePolicy(4096)) | |
| The main DIY object. More... | |
|
inline |
The main DIY object.
Helper functions specify how to: create an empty block, destroy a block (a function that's expected to upcast and delete), serialize a block
| comm | communicator |
| threads | number of threads DIY can use |
| limit | number of blocks to store in memory |
| create | block create function; master manages creation if create != 0 |
| destroy | block destroy function; master manages destruction if destroy != 0 |
| storage | storage object (path, method, etc.) for storing temporary blocks being shuffled in/out of core |
| save | block save function; master manages saving if save != 0 |
| load | block load function; master manages loading if load != 0 |
1.8.6