#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <mpi.h>
#include <yaxt.h>
#include "tests.h"
struct test_message {
int rank;
const int *pos;
int num_pos;
};
int rank;
MPI_Datatype datatype;
};
Xt_exchanger
Xt_exchanger
Xt_exchanger
Xt_exchanger
void * dst_data);
typedef Xt_exchanger (*exchanger_new_func) (
int nsend,
int nrecv,
static exchanger_new_func *parse_options(int *argc, char ***argv);
static void
test_bcast(
MPI_Comm comm, exchanger_new_func exchanger_new);
static void
test_gather(
MPI_Comm comm, exchanger_new_func exchanger_new);
static void
test_all2all(
MPI_Comm comm, exchanger_new_func exchanger_new);
static void
test_rr(
MPI_Comm comm, exchanger_new_func exchanger_new);
int main(int argc, char **argv)
{
int my_rank, comm_size;
exchanger_new_func *exchangers_new = parse_options(&argc, &argv);
for (size_t i = 0; exchangers_new[i] != (exchanger_new_func)0; ++i) {
exchanger_new_func exchanger_new = exchangers_new[i];
}
free(exchangers_new);
MPI_Finalize();
return TEST_EXIT_CODE;
}
static exchanger_new_func *parse_options(int *argc, char ***argv)
{
exchanger_new_func *exchangers_new = malloc(2 * sizeof (*exchangers_new));
exchangers_new[1] = (exchanger_new_func)0;
size_t cur_ex = 0;
int opt;
while ((opt = getopt(*argc, *argv, "m:")) != -1) {
switch (opt) {
case 'm':
if (!strcmp(optarg, "irecv_isend"))
exchangers_new[cur_ex] = xt_exchanger_irecv_isend_new;
else if (!strcmp(optarg, "irecv_isend_packed"))
exchangers_new[cur_ex] = xt_exchanger_irecv_isend_packed_new;
else if (!strcmp(optarg, "irecv_send"))
exchangers_new[cur_ex] = xt_exchanger_irecv_send_new;
else if (!strcmp(optarg, "mix_irecv_isend"))
exchangers_new[cur_ex] = xt_exchanger_mix_isend_irecv_new;
else {
fprintf(stderr, "Unknown exchanger constructor requested %s\n",
optarg);
exit(EXIT_FAILURE);
}
++cur_ex;
void *temp = realloc(exchangers_new,
sizeof (*exchangers_new) * (cur_ex + 1));
if (!temp) {
perror("failed reallocation");
abort();
}
exchangers_new = temp;
exchangers_new[cur_ex] = (exchanger_new_func)0;
}
}
return exchangers_new;
}
static void
test_bcast(
MPI_Comm comm, exchanger_new_func exchanger_new)
{
int my_rank, comm_size;
for (int i = 0; i < comm_size; ++i) {
int nsend = 0;
int nrecv = my_rank != i;
if (my_rank == i) {
nsend = comm_size - 1;
send_msgs = malloc((size_t)nsend * sizeof (*send_msgs));
if (send_msgs == 0) {
perror("Failed to allocate message meta-data");
abort();
}
for (size_t j = 0; j < (size_t)i; ++j)
for (size_t j = (size_t)i; j < (size_t)nsend; ++j)
.datatype=MPI_INT};
}
{{.
rank=-1, .datatype=MPI_DATATYPE_NULL},
{.rank=i, .datatype=MPI_INT}};
Xt_exchanger exchanger = exchanger_new(nsend, nrecv,
send_msgs,
recv_msgs + (my_rank != i),
comm, 0);
int src_data[1] = { my_rank == i ? 4711 : -1 };
int dst_data[1] = { my_rank == i ? 4711 : -1 };
if (dst_data[0] != 4711) PUT_ERR("invalid data\n");
free(send_msgs);
}
}
static void
test_gather(
MPI_Comm comm, exchanger_new_func exchanger_new)
{
int my_rank, comm_size;
MPI_Datatype *dt_by_ofs = malloc((size_t)comm_size * sizeof (*dt_by_ofs));
if (!dt_by_ofs) {
perror("Failed to allocate receive datatypes");
abort();
}
dt_by_ofs[0] = MPI_INT;
for (size_t j = 1; j < (size_t)comm_size; ++j)
{
MPI_Type_indexed(1, (int[]){1}, (int[]){(int)j}, MPI_INT, dt_by_ofs + j);
MPI_Type_commit(dt_by_ofs + j);
}
int *dst_data = malloc(((size_t)comm_size - 1) * sizeof (*dst_data) * 2);
if (comm_size - 1 && !dst_data) {
perror("Failed to allocate message receive buffer");
abort();
}
for (int i = 0; i < comm_size; ++i) {
int nsend = i != my_rank;
size_t nrecv = 0;
if (my_rank == i) {
nrecv = (size_t)comm_size - 1;
recv_msgs = malloc(nrecv * sizeof (*recv_msgs) * 2);
if (nrecv && !recv_msgs) {
perror("Failed to allocate message meta-data");
abort();
}
for (size_t j = 0; j < nrecv; ++j) {
recv_msgs[j].
rank = (i + (int)j + 1)%comm_size;
recv_msgs[j + nrecv].
rank = (comm_size - (int)j - 1 + i)%comm_size;
recv_msgs[j + nrecv].
datatype = dt_by_ofs[j];
}
}
enum { exchange_fwd, exchange_rev, num_exchanges };
Xt_exchanger exchanger[num_exchanges];
for (size_t j = 0; j < num_exchanges; ++j)
exchanger[j] = exchanger_new(nsend, (int)nrecv,
send_msgs, recv_msgs + j * nrecv, comm, 0);
int src_data[1] = {(my_rank+comm_size-i)%comm_size};
for (size_t j = 0; j < 2 * nrecv; ++j)
dst_data[j] = -1;
for (size_t j = 0; j < num_exchanges; ++j)
for (size_t j = 0; j < nrecv; ++j)
if (((size_t)dst_data[j] != j + 1)
|| (dst_data[nrecv + j] != comm_size - (int)j - 1))
PUT_ERR("invalid data\n");
free(recv_msgs);
}
free(dst_data);
for (size_t j = 1; j < (size_t)comm_size; ++j)
MPI_Type_free(dt_by_ofs + j);
free(dt_by_ofs);
}
static void
test_all2all(
MPI_Comm comm, exchanger_new_func exchanger_new)
{
int my_rank, comm_size;
int nsend = comm_size - 1;
int nrecv = comm_size - 1;
struct Xt_redist_msg *send_msgs = malloc((
size_t)nsend *
sizeof (*send_msgs));
if (nsend && !send_msgs) {
perror("Failed to allocate tx message meta-data");
abort();
}
for (size_t j = 0; j < (size_t)nsend; ++j)
struct Xt_redist_msg *recv_msgs = malloc((
size_t)nrecv *
sizeof (*recv_msgs));
if (nrecv && !recv_msgs) {
perror("Failed to allocate rx message meta-data");
abort();
}
int *dst_data = malloc((size_t)comm_size * sizeof (*dst_data));
if (!dst_data) {
perror("Failed to allocate recv data");
abort();
}
MPI_Datatype *dt_by_ofs = malloc((size_t)comm_size * sizeof (*dt_by_ofs));
if (!dt_by_ofs) {
perror("Failed to allocate datatypes");
abort();
}
dt_by_ofs[0] = my_rank != 0 ? MPI_INT : MPI_DATATYPE_NULL;
for (size_t i = 1; i < (size_t)comm_size; ++i)
if (i != (size_t)my_rank) {
MPI_Type_indexed(1, (int[]){1}, (int[]){(int)i}, MPI_INT, dt_by_ofs + i);
MPI_Type_commit(dt_by_ofs + i);
} else
dt_by_ofs[i] = MPI_DATATYPE_NULL;
for (size_t i = 0; i < (size_t)comm_size - 1; ++i) {
for (size_t j = 0; j < (size_t)nsend; ++j) {
int ofs = my_rank + 1 + (int)i + (int)j;
send_msgs[j].
rank = (ofs + (ofs >= comm_size + my_rank))%comm_size;
}
for (size_t j = 0; j < (size_t)comm_size - 1; ++j) {
for (size_t k = 0; k < (size_t)nrecv; ++k) {
int ofs = ((int)i + (int)j + (int)k)%(comm_size - 1);
ofs += ofs >= my_rank;
}
Xt_exchanger exchanger = exchanger_new(nsend, nrecv,
send_msgs,
recv_msgs,
int src_data[1] = {my_rank};
for (size_t k = 0; k < (size_t)comm_size; ++k)
dst_data[k] = my_rank;
for (int k = 0; k < comm_size; ++k)
if (dst_data[k] != k) PUT_ERR("invalid data\n");
}
}
for (size_t i = 1; i < (size_t)comm_size; ++i)
if (i != (size_t)my_rank)
MPI_Type_free(dt_by_ofs + i);
free(dt_by_ofs);
free(dst_data);
free(recv_msgs);
free(send_msgs);
}
static void
test_rr(
MPI_Comm comm, exchanger_new_func exchanger_new)
{
int my_rank, comm_size;
for (int i = 1; i < comm_size; ++i) {
enum { nsend = 1, nrecv = 1 };
= {{.
rank=(my_rank + comm_size - i)%comm_size, .
datatype=MPI_INT}};
Xt_exchanger exchanger = exchanger_new(nsend, nrecv, send_msgs,
recv_msgs, comm, 0);
int src_data[1] = {my_rank};
int dst_data[1] = {-1};
if (dst_data[0] != (my_rank + comm_size - i)%comm_size)
PUT_ERR("invalid data\n");
}
}