26static void print_func(
const char *msg,
int msglen,
int output_unit) {
28 if (output_unit == 0) {
37static inline int imin(
int x,
int y) {
return (x < y ? x : y); }
45 int cart_dims[2], cart_periods[2], cart_coords[2];
49 assert(0 < nrows && 0 < ncols);
50 int *row_dist = malloc(nrows *
sizeof(
int));
51 int *col_dist = malloc(ncols *
sizeof(
int));
52 assert(row_dist != NULL && col_dist != NULL);
53 for (
int i = 0;
i < nrows;
i++) {
54 row_dist[
i] =
i % cart_dims[0];
56 for (
int i = 0;
i < ncols;
i++) {
57 col_dist[
i] =
i % cart_dims[1];
72 const int size_max,
int sizes[nsizes]) {
73 assert(0 < size_min && size_min <= size_max);
74 const int range = size_max - size_min + 1;
75 for (
int i = 0;
i < nsizes;
i++) {
76 sizes[
i] = (1 < range ? size_min + rand() % range : size_max);
86 const int nrows_max,
const int ncols_min,
92 assert(0 < nrows && 0 < ncols);
93 int *row_sizes = malloc(nrows *
sizeof(
int));
94 int *col_sizes = malloc(ncols *
sizeof(
int));
95 assert(row_sizes != NULL && col_sizes != NULL);
99 dbm_create(&matrix, dist,
"some name", nrows, ncols, row_sizes, col_sizes);
112 const int *row_sizes, *col_sizes;
119#pragma omp for collapse(2)
120 for (
int row = 0; row < nrows; row++) {
121 for (
int col = 0; col < ncols; col++) {
128 int *reserve_row = NULL, *reserve_col = NULL;
130 reserve_row = malloc(nblocks *
sizeof(
int));
131 reserve_col = malloc(nblocks *
sizeof(
int));
132 assert(reserve_row != NULL && reserve_col != NULL);
135#pragma omp for collapse(2)
136 for (
int row = 0; row < nrows; row++) {
137 for (
int col = 0; col < ncols; col++) {
140 reserve_row[iblock] = row;
141 reserve_col[iblock] = col;
146 assert(iblock == nblocks);
163 int row, col, row_size, col_size;
167 const int shift = (31 * row + 17 * col) % 101;
168 const int block_size = row_size * col_size;
169 for (
int i = 0;
i < block_size;
i++) {
170 block[
i] = 1.0 / (
i + 1 + shift);
184 const char *
const fixed_env = getenv(
"DBM_MINIAPP_FIXED");
185 const bool fixed = (NULL != fixed_env && 0 != atoi(fixed_env));
203 const char *
const verify_env = getenv(
"DBM_MULTIPLY_VERIFY");
204 const int skip_verify = (NULL == verify_env ? 0 : (atoi(verify_env) + 1));
206 if (0 == skip_verify) {
214 const double time_start_multiply = omp_get_wtime();
215 dbm_multiply(
false,
false, 1.0, matrix_a, matrix_b, 1.0, matrix_c,
false,
217 const double time_end_multiply = omp_get_wtime();
220 printf(
"%5i x %5i x %5i with %3i x %3i x %3i blocks: ", M, N, K, m, n, k);
223 if (NULL != matrix_d) {
224 dbm_multiply(
false,
false, 1.0, matrix_a, matrix_b, 1.0, matrix_d,
false,
227 const double maxeps = 1E-5, epsilon =
dbm_maxeps(matrix_d, matrix_c);
228 if (maxeps < epsilon) {
230 fprintf(stderr,
"Failed validation (epsilon=%f).\n", epsilon);
238 const double duration = time_end_multiply - time_start_multiply;
239 printf(
"%6.3f s => %6.1f GFLOP/s\n", duration, 1e-9 * flop / duration);
254 const char *
const delims =
"x,;:|/";
256 while (ntriplet < 3 &&
'\0' != *arg) {
258 const long value = strtol(arg, &end, 10);
259 if (end == arg || value <= 0 || INT_MAX < value) {
262 triplet[ntriplet++] = (int)value;
263 for (arg = end;
'\0' != *arg && NULL != strchr(delims, *arg); ++arg) {
266 for (
int i = ntriplet; 0 < ntriplet &&
i < 3;
i++) {
267 triplet[
i] = triplet[0];
269 return (0 < ntriplet &&
'\0' == *arg);
280 bool valid = (0 < nargs);
281 for (
int i = 0; valid &&
i < nargs;
i += 2) {
282 int mnk[3], MNK[3] = {128, 128, 128};
296int main(
int argc,
char *argv[]) {
297 int result = EXIT_SUCCESS;
311 int dims[2] = {0, 0};
313 const int periods[2] = {
true,
true};
317 printf(
"OpenMP-threads: %i GPUs: %i", omp_get_max_threads(),
319#if defined(__parallel)
320 printf(
" MPI-ranks: %i MPI-cart: %i x %i", nranks, dims[0], dims[1]);
352 FILE *
const file = fopen(argv[1],
"r");
356 while (valid && NULL != fgets(buffer,
sizeof(buffer), file)) {
357 char *args[2] = {NULL, NULL};
359 for (
char *arg = strtok(buffer,
" \t\r\n"); NULL != arg;
360 arg = strtok(NULL,
" \t\r\n")) {
367 if (valid && 0 < nargs) {
377 fprintf(stderr,
"Usage: %s [file | mxnxk [MxNxK] ...]\n", argv[0]);
379 result = EXIT_FAILURE;
383 if (EXIT_SUCCESS == result) {
int cp_mpi_comm_size(const cp_mpi_comm_t comm)
Wrapper around MPI_Comm_size.
cp_mpi_comm_t cp_mpi_cart_create(const cp_mpi_comm_t comm_old, const int ndims, const int dims[], const int periods[], const int reorder)
Wrapper around MPI_Cart_create.
void cp_mpi_init(int *argc, char ***argv)
Initialize MPI with MPI_THREAD_MULTIPLE or attach to an active MPI.
int cp_mpi_comm_c2f(const cp_mpi_comm_t comm)
Wrapper around MPI_Comm_c2f.
cp_mpi_comm_t cp_mpi_get_comm_world(void)
Returns MPI_COMM_WORLD.
void cp_mpi_cart_get(const cp_mpi_comm_t comm, int maxdims, int dims[], int periods[], int coords[])
Wrapper around MPI_Cart_get.
void cp_mpi_sum_int64(int64_t *values, const int count, const cp_mpi_comm_t comm)
Wrapper around MPI_Allreduce for op MPI_SUM and datatype MPI_INT64_T.
void cp_mpi_comm_free(cp_mpi_comm_t *comm)
Wrapper around MPI_Comm_free.
void cp_mpi_dims_create(const int nnodes, const int ndims, int dims[])
Wrapper around MPI_Dims_create.
void cp_mpi_finalize(void)
Detach from MPI and finalize it only if cp_mpi_init initialized it.
int cp_mpi_comm_rank(const cp_mpi_comm_t comm)
Wrapper around MPI_Comm_rank.
void dbm_distribution_new(dbm_distribution_t **dist_out, const int fortran_comm, const int nrows, const int ncols, const int row_dist[nrows], const int col_dist[ncols])
Creates a new two dimensional distribution.
void dbm_distribution_release(dbm_distribution_t *dist)
Decreases the reference counter of the given distribution.
void dbm_library_finalize(void)
Finalizes the DBM library.
void dbm_library_print_stats(const int fortran_comm, void(*print_func)(const char *, int, int), const int output_unit)
Prints statistics gathered by the DBM library.
void dbm_library_init(void)
Initializes the DBM library.
void dbm_reserve_blocks(dbm_matrix_t *matrix, const int nblocks, const int rows[], const int cols[])
Adds list of blocks efficiently. The blocks will be filled with zeros. This routine must always be ca...
bool dbm_iterator_blocks_left(const dbm_iterator_t *iter)
Tests whether the given iterator has any block left.
void dbm_iterator_stop(dbm_iterator_t *iter)
Releases the given iterator.
void dbm_get_col_sizes(const dbm_matrix_t *matrix, int *ncols, const int **col_sizes)
Returns the column block sizes of the given matrix.
void dbm_create(dbm_matrix_t **matrix_out, dbm_distribution_t *dist, const char name[], const int nrows, const int ncols, const int row_sizes[nrows], const int col_sizes[ncols])
Creates a new matrix.
void dbm_iterator_start(dbm_iterator_t **iter_out, const dbm_matrix_t *matrix)
Creates an iterator for the blocks of the given matrix. The iteration order is not stable....
void dbm_iterator_next_block(dbm_iterator_t *iter, int *row, int *col, double **block, int *row_size, int *col_size)
Returns the next block from the given iterator.
void dbm_get_row_sizes(const dbm_matrix_t *matrix, int *nrows, const int **row_sizes)
Returns the row block sizes of the given matrix.
void dbm_copy(dbm_matrix_t *matrix_a, const dbm_matrix_t *matrix_b)
Copies content of matrix_b into matrix_a. Matrices must have the same row/col block sizes and distrib...
double dbm_maxeps(const dbm_matrix_t *matrix_a, const dbm_matrix_t *matrix_b)
Calculates maximum relative difference between matrix_a and matrix_b.
int dbm_get_stored_coordinates(const dbm_matrix_t *matrix, const int row, const int col)
Returns the MPI rank on which the given block should be stored.
void dbm_release(dbm_matrix_t *matrix)
Releases a matrix and all its ressources.
static void print_func(const char *msg, int msglen, int output_unit)
Wrapper for printf, passed to dbm_library_print_stats.
static void set_some_sizes(const int nsizes, const int size_min, const int size_max, int sizes[nsizes])
Private routine for drawing block sizes from [size_min, size_max].
static bool run_benchmarks(const int nargs, char *args[], const cp_mpi_comm_t comm)
Private routine for running benchmarks given as pairs of triplets, i.e., block sizes followed by the ...
static dbm_distribution_t * create_dist(const int nrows, const int ncols, const cp_mpi_comm_t comm)
Private routine for creating a distribution.
static int imin(int x, int y)
Returns the smaller of the two integers (missing from the C standard).
void benchmark_multiply(const int M, const int N, const int K, const int m, const int n, const int k, const cp_mpi_comm_t comm)
Run a benchmark of dbm_multiply with given block sizes. The blocks of A have 1 to m rows and those of...
static bool parse_triplet(const char *arg, int triplet[3])
Private routine for parsing a triplet like MxNxK, where omitted components default to the first one....
static void set_all_blocks(dbm_matrix_t *matrix)
Private routine for setting all blocks.
static dbm_matrix_t * create_some_matrix(const int nrows, const int ncols, const int nrows_min, const int nrows_max, const int ncols_min, const int ncols_max, const cp_mpi_comm_t comm)
Private routine for creating a distribution and an empty matrix.
static void reserve_all_blocks(dbm_matrix_t *matrix)
Private routine for reserving all blocks of the given matrix.
void dbm_multiply(const bool transa, const bool transb, const double alpha, const dbm_matrix_t *matrix_a, const dbm_matrix_t *matrix_b, const double beta, dbm_matrix_t *matrix_c, const bool retain_sparsity, const double filter_eps, int64_t *flop)
Performs a multiplication of two dbm_matrix_t matrices. See dbm_matrix.h for details.
static void const int const int i
int main()
Unit test of the C-interface provided via libcp2k.h.
int offload_get_device_count(void)
Returns the number of available devices.
void offload_set_chosen_device(int device_id)
Selects the chosen device to be used.
void offload_mempool_stats_print(int fortran_comm, void(*print_func)(const char *, int, int), int output_unit)
Print allocation statistics..
Internal struct for storing a two dimensional distribution.
Internal struct for storing a block iterator.
Internal struct for storing a matrix.
dbm_distribution_t * dist