|
underling
0.3.2
|
Provides a parallel, pencil-based 3D Cartesian domain decomposition atop FFTW MPI. The decomposition splits the 3D domain n0 by n1 by n2 across the 2D Cartesian topology given by pA by pB. Parallel transposes and local reordering are used to make the domain "long" (and often stride one) in each direction.
One generally defines an underling_grid, an underling_problem atop the grid, and then an underling_plan for executing transposes. The storage details in each transpose step are given by an underling_extents instance. Arbitrary-length interleaved data sets may be transposed. Methods which must be called collectively in the MPI sense are marked in their descriptions.
Go to the source code of this file.
Classes | |
| struct | underling_extents |
A transparent type storing the local sizes, strides, and storage when the data is long in a particular direction n0, n1, or n2. More... | |
Storage details | |
| typedef double | underling_real |
| The real-valued scalar type used throughout the library. More... | |
| const underling_extents | UNDERLING_EXTENTS_INVALID |
| A static instance used to communicate wholly invalid, unusable extents. More... | |
| void | underling_fprint_extents (const underling_extents *extents, FILE *output_file) |
| Dump an instance's internals in a debugging-friendly format. More... | |
| int | underling_extents_cmp (const underling_extents *const e1, const underling_extents *const e2) |
| Compare two underling_extents instances using lexicographic ordering. More... | |
Library initialization and cleanup | |
| int | underling_only_init (int *argc, char **argv[]) |
| Initialize underling. More... | |
| int | underling_init (int *argc, char **argv[], int nthreads) |
| Initialize MPI (if necessary), FFTW threading, FFTW MPI, and underling. More... | |
| void | underling_only_cleanup () |
| Release all resources held by underling. More... | |
| void | underling_cleanup () |
| Release all resources held by FFTW MPI, FFTW threading, and underling. More... | |
Creation and usage of underling_grids | |
| typedef struct underling_grid_s * | underling_grid |
| A type encapsulating a reusable domain-to-processor mapping. More... | |
| underling_grid | underling_grid_create (MPI_Comm comm, int n0, int n1, int n2, int pA, int pB) |
| Collectively create a reusable domain-to-processor mapping across the given MPI communicator. More... | |
| int | underling_grid_pA_size (const underling_grid grid) |
Obtain the size of the processor grid in the pA direction. More... | |
| int | underling_grid_pB_size (const underling_grid grid) |
Obtain the size of the processor grid in the pB direction. More... | |
| void | underling_grid_destroy (underling_grid grid) |
| Destroy all resources associated with the given grid. More... | |
| void | underling_fprint_grid (const underling_grid grid, FILE *output_file) |
| Dump an instance's internals in a debugging-friendly format. More... | |
Creation and usage of underling_problems | |
| #define | UNDERLING_TRANSPOSE_LONG_N2_TO_LONG_N1 |
Flag indicating a transform from long in n2 to long in n1. More... | |
| #define | UNDERLING_TRANSPOSE_LONG_N1_TO_LONG_N0 |
Flag indicating a transform from long in n1 to long in n0. More... | |
| #define | UNDERLING_TRANSPOSE_LONG_N0_TO_LONG_N1 |
Flag indicating a transform from long in n0 to long in n1. More... | |
| #define | UNDERLING_TRANSPOSE_LONG_N1_TO_LONG_N2 |
Flag indicating a transform from long in n1 to long in n2. More... | |
| #define | UNDERLING_TRANSPOSE_NONE |
| Flag indicating that no transposes will be performed. More... | |
| #define | UNDERLING_TRANSPOSE_ALL |
| Convenience flag indicating all transform directions. More... | |
| typedef struct underling_problem_s * | underling_problem |
| A type encapsulating all parallel decomposition information, including required local storage and stride details. More... | |
| underling_problem | underling_problem_create (underling_grid grid, int howmany, unsigned transposed_flags) |
Collectively create an instance encapsulating the parallel decomposition details for a decomposition over grid containing howmany scalar fields of type underling_real. More... | |
| void | underling_problem_destroy (underling_problem problem) |
| Destroy all resources associated with the given problem. More... | |
| void | underling_fprint_problem (const underling_problem problem, FILE *output_file) |
| Dump an instance's internals in a debugging-friendly format. More... | |
| underling_extents | underling_local_extents (const underling_problem problem, int i) |
Obtain the processor-local sizes, storage details, and global starting offsets when the data is long in the ni direction. More... | |
| size_t | underling_local (const underling_problem problem, int i, int *start, int *size, int *stride, int *order) |
Obtain the processor-local sizes, storage details, and global starting offsets when the data is long in the ni direction. More... | |
| size_t | underling_local_memory (const underling_problem problem) |
| Find the amount of local storage necessary to plan and execute a problem. More... | |
| size_t | underling_local_memory_optimum (const underling_problem problem) |
| Find the amount of local storage necessary to merely hold a problem in memory. More... | |
| size_t | underling_local_memory_maximum (const underling_grid grid, const underling_problem problem) |
| Collectively find the maximum amount of per-processor memory required to handle the problem across all processors in the grid. More... | |
| size_t | underling_local_memory_minimum (const underling_grid grid, const underling_problem problem) |
| Collectively find the minimal amount of per-processor memory required to handle the problem across all processors in the grid. More... | |
| size_t | underling_global_memory (const underling_grid grid, const underling_problem problem) |
| Collectively find the global amount of memory required to handle the problem across all processors in the grid. More... | |
| size_t | underling_global_memory_optimum (const underling_grid grid, const underling_problem problem) |
| Find the theoretical optimum (minimum) amount of memory required to store the given problem on all processors on the given grid assuming no communications buffer overhead. More... | |
Creation and usage of underling_plans | |
| #define | UNDERLING_TRANSPOSED_LONG_N2 |
Flag indicating that "long in n2" storage is stored as n2 x (n0/pB x n1/pA) in row-major order. More... | |
| #define | UNDERLING_TRANSPOSED_LONG_N0 |
Flag indicating that "long in n0" storage is stored as n0 x (n1/pB x n2/pA) in row-major order. More... | |
| typedef struct underling_plan_s * | underling_plan |
| A type encapsulating the FFTW MPI invocations necessary to transition from being long in one direction to long in another. More... | |
| underling_plan | underling_plan_create (const underling_problem problem, underling_real *in, underling_real *out, unsigned transpose_flags, unsigned fftw_rigor_flags) |
| Collectively create an execution plan to solve the given decomposition problem using the given input and output buffers. More... | |
| void | underling_plan_destroy (underling_plan plan) |
| Destroy all resources associated with the given plan. More... | |
| void | underling_fprint_plan (const underling_plan plan, FILE *output_file) |
| Dump an instance's internals in a debugging-friendly format. More... | |
| int | underling_execute_long_n2_to_long_n1 (const underling_plan plan, underling_real *in, underling_real *out) |
Collectively transform data from being long in n2 within buffer in to being long in n1 within buffer out. More... | |
| int | underling_execute_long_n1_to_long_n0 (const underling_plan plan, underling_real *in, underling_real *out) |
Collectively transform data from being long in n1 within buffer in to being long in n0 within buffer out. More... | |
| int | underling_execute_long_n0_to_long_n1 (const underling_plan plan, underling_real *in, underling_real *out) |
Collectively transform data from being long in n0 within buffer in to being long in n1 within buffer out. More... | |
| int | underling_execute_long_n1_to_long_n2 (const underling_plan plan, underling_real *in, underling_real *out) |
Collectively transform data from being long in n1 within buffer in to being long in n2 within buffer out. More... | |
| #define UNDERLING_TRANSPOSE_ALL |
Convenience flag indicating all transform directions.
| #define UNDERLING_TRANSPOSE_LONG_N0_TO_LONG_N1 |
Flag indicating a transform from long in n0 to long in n1.
| #define UNDERLING_TRANSPOSE_LONG_N1_TO_LONG_N0 |
Flag indicating a transform from long in n1 to long in n0.
| #define UNDERLING_TRANSPOSE_LONG_N1_TO_LONG_N2 |
Flag indicating a transform from long in n1 to long in n2.
| #define UNDERLING_TRANSPOSE_LONG_N2_TO_LONG_N1 |
Flag indicating a transform from long in n2 to long in n1.
| #define UNDERLING_TRANSPOSE_NONE |
Flag indicating that no transposes will be performed.
Useful when pencil decomposition details are of interest but one does not need to execute any transposes. Parallel decomposition and stride order details will be available though memory requirements will not be.
When present, this flag overrides and disables all of UNDERLING_TRANSPOSE_LONG_N2_TO_LONG_N1, UNDERLING_TRANSPOSE_LONG_N1_TO_LONG_N0, UNDERLING_TRANSPOSE_LONG_N0_TO_LONG_N1, and UNDERLING_TRANSPOSE_LONG_N1_TO_LONG_N2.
| #define UNDERLING_TRANSPOSED_LONG_N0 |
Flag indicating that "long in n0" storage is stored as n0 x (n1/pB x n2/pA) in row-major order.
This differs from the normal storage documented at underling_grid_create. Using this flag may speed up underling_execute_long_n1_to_long_n0 and underling_execute_long_n0_to_long_n1. Both underling_local_extents and underling_local will automatically return information reflecting this storage choice.
| #define UNDERLING_TRANSPOSED_LONG_N2 |
Flag indicating that "long in n2" storage is stored as n2 x (n0/pB x n1/pA) in row-major order.
This differs from the normal storage documented at underling_grid_create. Using this flag may speed up underling_execute_long_n2_to_long_n1 and underling_execute_long_n1_to_long_n2. Both underling_local_extents and underling_local will automatically return information reflecting this storage choice.
| typedef struct underling_grid_s* underling_grid |
A type encapsulating a reusable domain-to-processor mapping.
| typedef struct underling_plan_s* underling_plan |
A type encapsulating the FFTW MPI invocations necessary to transition from being long in one direction to long in another.
Similar in nature to an fftw_plan.
| typedef struct underling_problem_s* underling_problem |
A type encapsulating all parallel decomposition information, including required local storage and stride details.
| typedef double underling_real |
The real-valued scalar type used throughout the library.
All stride and size information is given in terms of this type.
| void underling_cleanup | ( | ) |
Release all resources held by FFTW MPI, FFTW threading, and underling.
As necessary, calls are made to fftw_mpi_cleanup(), fftw_cleanup_threads(), and underling_only_cleanup(). Threading cleanup is only performed when threads are available. MPI_Finalize() is not invoked.
FFTW wisdom is neither gathered with fftw_mpi_gather_wisdom nor saved with fftw_wisdom_export_to_file. You may wish to perform your own FFTW wisdom handling prior to calling this method.
underling_only_init() initializes only underling without interacting with MPI or FFTW. | int underling_execute_long_n0_to_long_n1 | ( | const underling_plan | plan, |
| underling_real * | in, | ||
| underling_real * | out | ||
| ) |
Collectively transform data from being long in n0 within buffer in to being long in n1 within buffer out.
Appropriate MPI calls and data reordering will occur. The input and output buffers must be aligned identically to the input and output buffers provided during planning.
| plan | Plan to be executed. |
| in | Input buffer on which to execute the plan. For out-of-place transforms, this buffer's contents will be destroyed. |
| out | Output buffer on which to execute the plan. For in-place transforms, one must specify out == in. |
| int underling_execute_long_n1_to_long_n0 | ( | const underling_plan | plan, |
| underling_real * | in, | ||
| underling_real * | out | ||
| ) |
Collectively transform data from being long in n1 within buffer in to being long in n0 within buffer out.
Appropriate MPI calls and data reordering will occur. The input and output buffers must be aligned identically to the input and output buffers provided during planning.
| plan | Plan to be executed. |
| in | Input buffer on which to execute the plan. For out-of-place transforms, this buffer's contents will be destroyed. |
| out | Output buffer on which to execute the plan. For in-place transforms, one must specify out == in. |
| int underling_execute_long_n1_to_long_n2 | ( | const underling_plan | plan, |
| underling_real * | in, | ||
| underling_real * | out | ||
| ) |
Collectively transform data from being long in n1 within buffer in to being long in n2 within buffer out.
Appropriate MPI calls and data reordering will occur. The input and output buffers must be aligned identically to the input and output buffers provided during planning.
| plan | Plan to be executed. |
| in | Input buffer on which to execute the plan. For out-of-place transforms, this buffer's contents will be destroyed. |
| out | Output buffer on which to execute the plan. For in-place transforms, one must specify out == in. |
| int underling_execute_long_n2_to_long_n1 | ( | const underling_plan | plan, |
| underling_real * | in, | ||
| underling_real * | out | ||
| ) |
Collectively transform data from being long in n2 within buffer in to being long in n1 within buffer out.
Appropriate MPI calls and data reordering will occur. The input and output buffers must be aligned identically to the input and output buffers provided during planning.
| plan | Plan to be executed. |
| in | Input buffer on which to execute the plan. For out-of-place transforms, this buffer's contents will be destroyed. |
| out | Output buffer on which to execute the plan. For in-place transforms, one must specify out == in. |
| int underling_extents_cmp | ( | const underling_extents *const | e1, |
| const underling_extents *const | e2 | ||
| ) |
Compare two underling_extents instances using lexicographic ordering.
| e1 | First instance to compare. |
| e2 | Second instance to compare. |
*e1 is found, respectively, to be less than, to match, or be greater than *e2. | void underling_fprint_extents | ( | const underling_extents * | extents, |
| FILE * | output_file | ||
| ) |
Dump an instance's internals in a debugging-friendly format.
| extents | Extents to dump. |
| output_file | Desired output handle, which may be stdout or stderr. |
| void underling_fprint_grid | ( | const underling_grid | grid, |
| FILE * | output_file | ||
| ) |
Dump an instance's internals in a debugging-friendly format.
| grid | Grid to dump. |
| output_file | Desired output handle, which may be stdout or stderr. |
| void underling_fprint_plan | ( | const underling_plan | plan, |
| FILE * | output_file | ||
| ) |
Dump an instance's internals in a debugging-friendly format.
| plan | Plan to dump. |
| output_file | Desired output handle, which may be stdout or stderr. |
| void underling_fprint_problem | ( | const underling_problem | problem, |
| FILE * | output_file | ||
| ) |
Dump an instance's internals in a debugging-friendly format.
| problem | Problem to dump. |
| output_file | Desired output handle, which may be stdout or stderr. |
| size_t underling_global_memory | ( | const underling_grid | grid, |
| const underling_problem | problem | ||
| ) |
Collectively find the global amount of memory required to handle the problem across all processors in the grid.
| grid | Grid for which to retrieve information. |
| problem | Problem for which to retrieve information. |
| size_t underling_global_memory_optimum | ( | const underling_grid | grid, |
| const underling_problem | problem | ||
| ) |
Find the theoretical optimum (minimum) amount of memory required to store the given problem on all processors on the given grid assuming no communications buffer overhead.
| grid | Grid for which to retrieve information. |
| problem | Problem for which to retrieve information. |
| underling_grid underling_grid_create | ( | MPI_Comm | comm, |
| int | n0, | ||
| int | n1, | ||
| int | n2, | ||
| int | pA, | ||
| int | pB | ||
| ) |
Collectively create a reusable domain-to-processor mapping across the given MPI communicator.
The 3D domain n0 by n1 by n2 will be split across the 2D Cartesian topology given by pA by pB as follows:
(n0/pB x n1/pA) x n2.(n2/pA x n0/pB) x n1.(n1/pB x n2/pA) x n0.All orders given are row-major; the rightmost index is fastest. Expressions like n{0,1,2}/p{A,B} indicate that the n{0,1,2} direction is decomposed across a grid of size p{A,B}. It must be true that n0 >= pB, n1 >= pA, pB, and n2 >= pA. The parallel decomposition is balanced given communication overhead expectations.
Specifying zero for either or both of pA and pB results in an automatic decomposition of the communicator into a 2D Cartesian grid using MPI_Dims_create. Specifying zero for both pA and pB will "align" the resulting grid so that the larger of pA and pB decomposes the larger of n0 and n2.
| comm | MPI communicator indicating the processes to be used for the parallel domain decomposition. The communicator is cloned. |
| n0 | Global size of the domain in the n0 direction. |
| n1 | Global size of the domain in the n1 direction. |
| n2 | Global size of the domain in the n2 direction. |
| pA | Processor grid size in the pA direction. Providing zero causes automatic size selection. |
| pB | Processor grid size in the pB direction. Providing zero causes automatic size selection. |
| void underling_grid_destroy | ( | underling_grid | grid | ) |
Destroy all resources associated with the given grid.
| grid | Grid to be destroyed. |
| int underling_grid_pA_size | ( | const underling_grid | grid | ) |
Obtain the size of the processor grid in the pA direction.
| grid | Grid for which to retrieve information. |
pA direction. On failure, calls underling_error and returns null. pA processor grid direction. | int underling_grid_pB_size | ( | const underling_grid | grid | ) |
Obtain the size of the processor grid in the pB direction.
| grid | Grid for which to retrieve information. |
pB direction. On failure, calls underling_error and returns null. pB processor grid direction. | int underling_init | ( | int * | argc, |
| char ** | argv[], | ||
| int | nthreads | ||
| ) |
Initialize MPI (if necessary), FFTW threading, FFTW MPI, and underling.
As necessary, calls are made to MPI_Init(), fftw_init_threads(), fftw_plan_with_nthreads(), and finally fftw_mpi_init(), and finally underling_only_init. Threading initialization is only performed when threads are available.
FFTW wisdom is neither loaded with fftw_wisdom_import_from_file nor broadcast with fftw_mpi_broadcast_wisdom. You may wish to perform your own FFTW wisdom handling after this method has been called.
| argc | &argc from main(argc,argv). May be NULL if the caller cannot obtain &argc. |
| argv | &argv from main(argv,argv). May be NULL if the caller cannot obtain &argv. |
| nthreads | Number of threads to use for planning. If zero, the environment variable OMP_NUM_THREADS is used (for both OpenMP- and pthread-based FFTW installations). |
underling_only_init() initializes only underling without interacting with MPI or FFTW. | size_t underling_local | ( | const underling_problem | problem, |
| int | i, | ||
| int * | start, | ||
| int * | size, | ||
| int * | stride, | ||
| int * | order | ||
| ) |
Obtain the processor-local sizes, storage details, and global starting offsets when the data is long in the ni direction.
This is identical to the data obtainable via underling_local_extents but is provided in a more Fortran-ready interface. All strides and sizes are given in units of underling_real.
| [in] | problem | Problem for which to retrieve information. |
| [in] | i | Retrieve information when long in ni for i in {0, 1, 2}. |
| [in,out] | start | If non-NULL on entry, contains underling_extents.start on successful return. |
| [in,out] | size | If non-NULL on entry, contains underling_extents.size on successful return. |
| [in,out] | stride | If non-NULL on entry, contains underling_extents.stride on successful return. |
| [in,out] | order | If non-NULL on entry, contains underling_extents.order on successful return. |
| underling_extents underling_local_extents | ( | const underling_problem | problem, |
| int | i | ||
| ) |
Obtain the processor-local sizes, storage details, and global starting offsets when the data is long in the ni direction.
All strides and sizes are given in units of underling_real.
| problem | Problem for which to retrieve information. |
| i | Retrieve information when long in ni for i in {0, 1, 2}. |
| size_t underling_local_memory | ( | const underling_problem | problem | ) |
Find the amount of local storage necessary to plan and execute a problem.
This includes the storage to hold data in the long in n{0,1,2} directions as well as any additional communication buffer space required.
| problem | Problem for which to retrieve information. |
| size_t underling_local_memory_maximum | ( | const underling_grid | grid, |
| const underling_problem | problem | ||
| ) |
Collectively find the maximum amount of per-processor memory required to handle the problem across all processors in the grid.
| grid | Grid for which to retrieve information. |
| problem | Problem for which to retrieve information. |
| size_t underling_local_memory_minimum | ( | const underling_grid | grid, |
| const underling_problem | problem | ||
| ) |
Collectively find the minimal amount of per-processor memory required to handle the problem across all processors in the grid.
| grid | Grid for which to retrieve information. |
| problem | Problem for which to retrieve information. |
| size_t underling_local_memory_optimum | ( | const underling_problem | problem | ) |
Find the amount of local storage necessary to merely hold a problem in memory.
This includes holding the data long in the n{0,1,2} directions but not any additional communication buffer overhead.
| problem | Problem for which to retrieve information. |
| void underling_only_cleanup | ( | ) |
Release all resources held by underling.
You may wish to invoke clean up methods for FFTW MPI, FFTW threading, and MPI after this method has been called.
underling_cleanup() cleans up underling's entire non-MPI prerequisite chain (FFTW, FFTW threads, FFTW MPI) in one call. | int underling_only_init | ( | int * | argc, |
| char ** | argv[] | ||
| ) |
Initialize underling.
Caller must have initialized MPI, FFTW MPI, and set any required FFTW threading parameters prior to invoking this method.
| argc | &argc from main(argc,argv). May be NULL if the caller cannot obtain &argc. |
| argv | &argv from main(argv,argv). May be NULL if the caller cannot obtain &argv. |
underling_init() initializes underling's entire prerequisite chain (MPI, FFTW, FFTW threads, FFTW MPI) in one call. | underling_plan underling_plan_create | ( | const underling_problem | problem, |
| underling_real * | in, | ||
| underling_real * | out, | ||
| unsigned | transpose_flags, | ||
| unsigned | fftw_rigor_flags | ||
| ) |
Collectively create an execution plan to solve the given decomposition problem using the given input and output buffers.
Creating a plan may have significant cost. Once a plan is created, it may be repeatedly used on different, identically aligned buffers without incurring this one time overhead.
Out-of-place plans are created by specifying input and output buffers such that in != out. Executing an out-of-place plan will always destroy the contents of the input buffer in. In-place plans can be created by specifying in == out. In-place plans always use less memory but will often run more slowly than out-of-place plans.
Planning cost can be reduced by only requesting the transform capabilities you require using transpose_flags. It should contain the bitwise OR of one or more of the following:
It is an error to execute a transpose when the corresponding flag was not provided to this method. It is an error to execute any transpose when UNDERLING_TRANSPOSE_NONE is provided to this method (though decomposition information can still be obtained in this case).
Planning cost may be modified using fftw_rigor_flags. It must be one of the following:
Longer planning will usually result in shorter execution time and higher performance. See the FFTW manual regarding planner flags for more details. Note that using any value other than FFTW_ESTIMATE will cause the buffers in and out to be overwritten during the invocation.
| problem | Problem for which a plan is sought. |
| in | Input buffer of size at least underling_local_memory(problem) underling_reals used as the source data. |
| out | Output buffer of size at least underling_local_memory(problem) underling_reals used as the target data. |
| transpose_flags | Desired transposes to plan. Specifying zero is equivalent to specifying UNDERLING_TRANSPOSE_ALL. |
| fftw_rigor_flags | Desired FFTW planning rigor. Specifying zero is equivalent to specifying FFTW_MEASURE. |
| void underling_plan_destroy | ( | underling_plan | plan | ) |
Destroy all resources associated with the given plan.
| plan | Plan to be destroyed. |
| underling_problem underling_problem_create | ( | underling_grid | grid, |
| int | howmany, | ||
| unsigned | transposed_flags | ||
| ) |
Collectively create an instance encapsulating the parallel decomposition details for a decomposition over grid containing howmany scalar fields of type underling_real.
| grid | Domain-to-processor mapping to use. One grid may be used to create multiple underling_problem instances. |
| howmany | Number of interleaved scalar fields of type underling_real to simultaneously transpose. |
| transposed_flags | Either zero or some combination of UNDERLING_TRANSPOSED_LONG_N2 and UNDERLING_TRANSPOSED_LONG_N0. |
| void underling_problem_destroy | ( | underling_problem | problem | ) |
Destroy all resources associated with the given problem.
| problem | Problem to be destroyed. |
| const underling_extents UNDERLING_EXTENTS_INVALID |
A static instance used to communicate wholly invalid, unusable extents.