#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <assert.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <mpi.h>
#include <yaxt.h>
#include "tests.h"
#include "ctest_common.h"
struct test_message {
int rank;
int num_pos;
const int *pos;
};
static void test_xmap(
int num_sends, const struct test_message send_messages[num_sends],
int num_recvs, const struct test_message recv_messages[num_recvs]);
int nsrc_com,
const struct Xt_com_list src_com[nsrc_com],
int ndst_com, const struct
Xt_com_list dst_com[ndst_com],
static void
test_strided_block_pos_alltoall(
MPI_Comm comm,
int nblk,
int blksz);
static void
parse_options(int *argc, char ***argv);
int main(int argc, char **argv)
{
int my_rank, comm_size;
if (comm_size != 3) {
MPI_Finalize();
return 77;
}
parse_options(&argc, &argv);
{
int num_src_intersections = 1;
.rank = (my_rank+1)%comm_size};
int num_dst_intersections = 1;
.rank = (my_rank+comm_size-1)%comm_size};
Xt_xmap xmap = xmi_new(num_src_intersections, &src_com,
num_dst_intersections, &dst_com,
int send_pos = 0;
int num_sends = 1;
struct test_message send_messages[1] = {{.rank = (my_rank+1)%comm_size,
.pos = &send_pos, .num_pos = 1}};
int recv_pos = 0;
int num_recvs = 1;
struct test_message recv_messages[1] = {{.rank = (my_rank+comm_size-1)%comm_size,
.pos = &recv_pos, .num_pos = 1}};
test_xmap(xmap, num_sends, send_messages, num_recvs, recv_messages);
}
{
int num_src_intersections = (my_rank == 0)?0:1;
.rank = 0};
int num_dst_intersections = (my_rank == 0)?2:0;
struct Xt_com_list dst_com[2] = {{.list = dst_idxlist, .rank = 1},
{.list = dst_idxlist, .rank = 2}};
Xt_xmap xmap = xmi_new(num_src_intersections, &src_com,
num_dst_intersections, dst_com,
int send_pos = 0;
int num_sends = (my_rank == 1)?1:0;
struct test_message send_messages[1] = {{.rank = 0, .pos = &send_pos,
.num_pos = 1}};
int recv_pos = 0;
int num_recvs = (my_rank == 0)?1:0;
struct test_message recv_messages[1] = {{.rank = 1, .pos = &recv_pos,
.num_pos = 1}};
test_xmap(xmap, num_sends, send_messages, num_recvs, recv_messages);
}
{
(
Xt_int)((my_rank+2)%comm_size) };
int num_src_intersections[3] = {2, 1, 0};
struct Xt_com_list src_com[2] = {{.list = src_intersection_idxlist[0],
.rank = 1},
{.list = src_intersection_idxlist[1],
.rank = (my_rank == 0)?2:0}};
int num_dst_intersections = 1;
struct Xt_com_list dst_com = {.list = dst_idxlist, .rank = (my_rank == 0)?1:0};
Xt_xmap xmap = xmi_new(num_src_intersections[my_rank], src_com + my_rank,
num_dst_intersections, &dst_com,
if (my_rank == 0) {
int send_pos[2] = {0,1};
int num_sends = 2;
struct test_message send_messages[2] = {{.rank = 1, .pos = send_pos+0,
.num_pos = 1},
{.rank = 2, .pos = send_pos+1,
.num_pos = 1}};
int recv_pos = 0;
int num_recvs = 1;
struct test_message recv_messages[1] = {{.rank = 1, .pos = &recv_pos,
.num_pos = 1}};
test_xmap(xmap, num_sends, send_messages, num_recvs, recv_messages);
} else if (my_rank == 1) {
int send_pos = 1;
int num_sends = 1;
struct test_message send_messages[1] = {{.rank = 0, .pos = &send_pos,
.num_pos = 1}};
int recv_pos = 0;
int num_recvs = 1;
struct test_message recv_messages[1] = {{.rank = 0, .pos = &recv_pos,
.num_pos = 1}};
test_xmap(xmap, num_sends, send_messages, num_recvs, recv_messages);
} else {
int num_sends = 0;
int recv_pos = 0;
int num_recvs = 1;
struct test_message recv_messages[1] = {{.rank = 0, .pos = &recv_pos,
.num_pos = 1}};
test_xmap(xmap, num_sends, NULL, num_recvs, recv_messages);
}
}
{
static const Xt_int src_indices[3][5]
= {{0,1,2,3,4}, {3,4,5,6,7}, {6,7,8,0,1}};
static const Xt_int dst_indices[9] = {0,1,2,3,4,5,6,7,8};
struct Xt_com_list src_com[3] = {{.list = src_idxlist, .rank = 0},
{.list = src_idxlist, .rank = 1},
{.list = src_idxlist, .rank = 2}};
Xt_xmap xmap = xmi_new(3, src_com, 3, dst_com,
static const int send_pos[3][5] = {{0,1,2,3,4}, {2,3,4}, {2}};
static const int num_send_pos[3] = {5, 3, 1};
struct test_message send_messages[3] = {{.rank = 0,
.pos = send_pos[my_rank],
.num_pos = num_send_pos[my_rank]},
{.rank = 1,
.pos = send_pos[my_rank],
.num_pos = num_send_pos[my_rank]},
{.rank = 2,
.pos = send_pos[my_rank],
.num_pos = num_send_pos[my_rank]}};
static const int recv_pos[3][5] = {{0,1,2,3,4}, {5,6,7}, {8}};
static const int num_recv_pos[3] = {5, 3, 1};
struct test_message recv_messages[3] = {{.rank = 0, .pos = recv_pos[0],
.num_pos = num_recv_pos[0]},
{.rank = 1, .pos = recv_pos[1],
.num_pos = num_recv_pos[1]},
{.rank = 2, .pos = recv_pos[2],
.num_pos = num_recv_pos[2]}};
test_xmap(xmap, 3, send_messages, 3, recv_messages);
}
{
Xt_int src_indices[2][2] = {{0,2}, {1,2}};
int num_src_intersections, num_dst_intersections;
if (my_rank == 2) {
src_com = NULL;
num_src_intersections = 0;
dst_com = malloc(2 * sizeof(*dst_com));
num_dst_intersections = 2;
Xt_int dst_indices[3] = {0,1,2};
} else {
src_com = malloc(1 * sizeof(*src_com));
num_src_intersections = 1;
dst_com = NULL;
num_dst_intersections = 0;
}
Xt_xmap xmap = xmi_new(num_src_intersections, src_com,
num_dst_intersections, dst_com,
if (my_rank == 2) {
static const int recv_pos[2][2] = {{0,2}, {1}};
static const struct test_message recv_messages[2]
= {{.rank = 0, .pos = recv_pos[0], .num_pos = 2},
{.rank = 1, .pos = recv_pos[1], .num_pos = 1}};
test_xmap(xmap, 0, NULL, 2, recv_messages);
} else {
static const int send_pos[2][2] = {{0,1}, {0}};
static const int num_send_pos[2] = {2, 1};
struct test_message send_messages = {.rank = 2,
.pos = send_pos[my_rank],
.num_pos = num_send_pos[my_rank]};
test_xmap(xmap, 1, &send_messages, 0, NULL);
}
for (int i = 0; i < num_dst_intersections; ++i)
free(dst_com);
for (int i = 0; i < num_src_intersections; ++i)
free(src_com);
}
{
enum { count = 6 };
Xt_int src_indices[count] = {0,5,1,4,2,3};
Xt_int dst_indices[count] = {5,4,3,2,1,0};
Xt_int intersection_indices[count] = {0,1,2,3,4,5};
.rank = (my_rank + 1) % comm_size};
.rank = (comm_size + my_rank - 1) % comm_size};
Xt_xmap xmap = xmi_new(1, &src_com, 1, &dst_com,
for (size_t i = 0; i < sizeof(reorder_types) / sizeof(reorder_types[0]);
++i) {
int send_msg_pos[count] = {0,2,4,5,3,1};
struct test_message send_messages =
{.pos = send_msg_pos, .num_pos = 6};
send_messages.rank = (my_rank + 1) % comm_size;
int recv_msg_pos[count] = {5,4,3,2,1,0};
struct test_message recv_messages =
{.pos = recv_msg_pos, .num_pos = 6};
recv_messages.rank = (comm_size + my_rank - 1) % comm_size;
switch((int)curr_reorder_type) {
send_msg_pos, (size_t)count, recv_msg_pos);
break;
recv_msg_pos, (size_t)count, send_msg_pos);
break;
default:
break;
}
test_xmap(xmap_reorder, 1, &send_messages, 1, &recv_messages);
}
}
{
enum { count = 12, nlev = 6, nproma = 4, nblk = 3};
static const Xt_int src_indices[count] = {0,1,2,3,4,5,6,7,8,9,10,11};
static const Xt_int dst_indices[count] = {0,1,2,3,4,5,6,7,8,9,10,11};
static const Xt_int intersection_indices[count] = {0,1,2,3,4,5,6,7,8,9,10,11};
int displacements[nlev];
for (int i = 0; i < (int)nlev; ++i) displacements[i] = i * nproma;
.rank = (my_rank + 1) % comm_size};
.rank = (comm_size + my_rank - 1) % comm_size};
Xt_xmap xmap = xmi_new(1, &src_com, 1, &dst_com,
int blocked_positions[(int)count * (int)nlev];
for (int i = 0, lev = 0; lev < (int)nlev; ++lev)
for (int blk = 0; blk < nblk; ++blk)
for (int idx = 0; idx < nproma; ++idx, ++i)
blocked_positions[i] = idx + (blk * nlev + lev) * nproma;
Xt_xmap xmap_single_level_blocked =
xmap_single_level_blocked, (int)nlev, displacements, displacements);
struct test_message send_messages =
{.pos = &(blocked_positions[0]), .num_pos = (int)nlev * (int)count};
send_messages.rank = (my_rank + 1) % comm_size;
struct test_message recv_messages =
{.pos = &(blocked_positions[0]), .num_pos = (int)nlev * (int)count};
recv_messages.rank = (comm_size + my_rank - 1) % comm_size;
test_xmap(xmap_multi_level_blocked, 1, &send_messages, 1, &recv_messages);
}
MPI_Finalize();
return TEST_EXIT_CODE;
}
static void
test_strided_block_pos_alltoall(
MPI_Comm comm,
int nblk,
int blksz)
{
int comm_rank, comm_size;
xmalloc(2 * (
size_t)comm_size *
sizeof(*src_com)),
*dst_com = src_com + comm_size;
=
xmalloc((
size_t)nblk * (
size_t)blksz
struct test_message *ref_src_msg =
xmalloc(2 * (
size_t)comm_size *
sizeof(*ref_src_msg)),
*ref_dst_msg = ref_src_msg + comm_size;
for (int rank = 0; rank < comm_size; ++rank) {
for (int j = 0; j < nblk; ++j)
for (int i = 0; i < blksz; ++i)
transfer_pos[rank][j][i] = i + j*blksz*comm_size;
#if defined __PGI && __PGIC__ <= 15
= (int *)transfer_pos + rank * nblk * blksz;
#else
= (int *)(transfer_pos + rank);
#endif
ref_src_msg[rank].rank = src_com[rank].
rank = rank;
#if defined __PGI && __PGIC__ <= 15
ref_dst_msg[rank].pos = dst_com[rank].transfer_pos
= (int *)transfer_pos + rank * nblk * blksz;
#else
ref_dst_msg[rank].pos = dst_com[rank].transfer_pos
= (int *)(transfer_pos + rank);
#endif
ref_dst_msg[rank].num_pos = dst_com[rank].num_transfer_pos = nblk*blksz;
ref_dst_msg[rank].
rank = dst_com[rank].
rank = rank;
}
test_xmap(xmap, comm_size, ref_src_msg, comm_size, ref_dst_msg);
free(ref_src_msg);
free(transfer_pos);
free(src_com);
}
const struct test_message msgs[num_msgs]) {
if (num_msgs == 0) {
if (iter != NULL)
PUT_ERR("ERROR: xt_xmap_get_*_iterator (iter should be NULL)\n");
} else if (iter == NULL) {
PUT_ERR("ERROR: xt_xmap_get_*_iterator (iter should not be NULL)\n");
} else {
int i = 0;
do {
PUT_ERR("ERROR: xt_xmap_iterator_get_rank\n");
PUT_ERR("ERROR: xt_xmap_iterator_get_num_transfer_pos\n");
bool mismatch = false;
for (int j = 0; j < msgs[i].num_pos; ++j)
mismatch |= (pos[j] != msgs[i].pos[j]);
if (mismatch)
PUT_ERR("ERROR: xt_xmap_iterator_get_transfer_pos\n");
int num_transfer_pos_ext
mismatch = false;
size_t ofs = 0;
for (size_t pe = 0; pe < (size_t)num_transfer_pos_ext; ++pe) {
int pos_ext_size = abs(pos_ext[pe].
size);
if (pos_ext[pe].
size > 0)
for (int j = 0; j < pos_ext_size; ++j)
mismatch |= (pos[ofs+(
size_t)j] != pos_ext[pe].
start + j);
else
for (int j = 0; j < pos_ext_size; ++j)
mismatch |= (pos[ofs+(
size_t)j] != pos_ext[pe].
start - j);
ofs += (size_t)pos_ext_size;
}
if (mismatch || (int)ofs != msgs[i].num_pos)
PUT_ERR("ERROR: xt_xmap_iterator_get_transfer_pos_ext\n");
++i;
if (i != num_msgs)
PUT_ERR("ERROR: xt_xmap_iterator_next (wrong number of message)\n");
}
}
static void test_xmap(
int num_sends, const struct test_message send_messages[num_sends],
int num_recvs, const struct test_message recv_messages[num_recvs]) {
enum { numXmaps2Test = 2 };
for (size_t i = 0; i < numXmaps2Test; ++i) {
PUT_ERR("ERROR: xt_xmap_get_num_destinations\n");
PUT_ERR("ERROR: xt_xmap_get_num_sources\n");
test_xmap_iter(send_iter, num_sends, send_messages);
test_xmap_iter(recv_iter, num_recvs, recv_messages);
}
}
static void
parse_options(int *argc, char ***argv)
{
int opt;
while ((opt = getopt(*argc, *argv, "m:")) != -1) {
switch (opt) {
case 'm':
if (!strcmp(optarg, "xt_xmap_intersection_new"))
else if (!strcmp(optarg, "xt_xmap_intersection_ext_new"))
else
{
fprintf(stderr, "Unknown xmap intersection constructor requested %s\n",
optarg);
exit(EXIT_FAILURE);
}
}
}
}
add versions of standard API functions not returning on error
void xt_quicksort_int_permutation(int *restrict a, size_t n, int *restrict permutation)
void xt_initialize(MPI_Comm default_comm)
struct Xt_xmap_ * Xt_xmap
struct Xt_idxlist_ * Xt_idxlist
Xt_idxlist xt_idxempty_new(void)
void xt_idxlist_delete(Xt_idxlist idxlist)
Xt_idxlist xt_idxvec_new(const Xt_int *idxlist, int num_indices)
#define xt_mpi_call(call, comm)
exchange map declarations
Xt_xmap xt_xmap_update_positions(Xt_xmap xmap, const int *src_positions, const int *dst_positions)
int xt_xmap_iterator_next(Xt_xmap_iter iter)
struct Xt_xmap_iter_ * Xt_xmap_iter
Xt_xmap xt_xmap_reorder(Xt_xmap xmap, enum xt_reorder_type type)
@ XT_REORDER_RECV_UP
optimise data access on receiver side
@ XT_REORDER_NONE
no reordering
@ XT_REORDER_SEND_UP
optimise data access on sender side
void xt_xmap_delete(Xt_xmap xmap)
Xt_xmap_iter xt_xmap_get_out_iterator(Xt_xmap xmap)
int xt_xmap_iterator_get_num_transfer_pos_ext(Xt_xmap_iter iter)
Xt_xmap xt_xmap_spread(Xt_xmap xmap, int num_repetitions, const int src_displacements[num_repetitions], const int dst_displacements[num_repetitions])
void xt_xmap_iterator_delete(Xt_xmap_iter iter)
int xt_xmap_get_num_destinations(Xt_xmap xmap)
Xt_xmap xt_xmap_copy(Xt_xmap xmap)
int xt_xmap_iterator_get_rank(Xt_xmap_iter iter)
int xt_xmap_get_num_sources(Xt_xmap xmap)
const struct Xt_pos_ext * xt_xmap_iterator_get_transfer_pos_ext(Xt_xmap_iter iter)
Xt_xmap_iter xt_xmap_get_in_iterator(Xt_xmap xmap)
int const * xt_xmap_iterator_get_transfer_pos(Xt_xmap_iter iter)
int xt_xmap_iterator_get_num_transfer_pos(Xt_xmap_iter iter)
Xt_xmap xt_xmap_intersection_ext_new(int num_src_intersections, const struct Xt_com_list src_com[num_src_intersections], int num_dst_intersections, const struct Xt_com_list dst_com[num_dst_intersections], Xt_idxlist src_idxlist, Xt_idxlist dst_idxlist, MPI_Comm comm)
Xt_xmap xt_xmap_intersection_pos_new(int num_src_msg, const struct Xt_com_pos src_com[num_src_msg], int num_dst_msg, const struct Xt_com_pos dst_com[num_dst_msg], MPI_Comm comm)
Xt_xmap xt_xmap_intersection_new(int num_src_intersections, const struct Xt_com_list src_com[num_src_intersections], int num_dst_intersections, const struct Xt_com_list dst_com[num_dst_intersections], Xt_idxlist src_idxlist, Xt_idxlist dst_idxlist, MPI_Comm comm)