Blame test/mpi/cxx/attr/attrtx.cxx

Packit Service c5cf8c
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
Packit Service c5cf8c
/*
Packit Service c5cf8c
 *  (C) 2001 by Argonne National Laboratory.
Packit Service c5cf8c
 *      See COPYRIGHT in top-level directory.
Packit Service c5cf8c
 */
Packit Service c5cf8c
/*
Packit Service c5cf8c
Packit Service c5cf8c
  Exercise communicator routines.
Packit Service c5cf8c
Packit Service c5cf8c
  This C++ version derived from a Fortran test program from ....
Packit Service c5cf8c
*/
Packit Service c5cf8c
Packit Service c5cf8c
#include "mpi.h"
Packit Service c5cf8c
Packit Service c5cf8c
#include "mpitestconf.h"
Packit Service c5cf8c
#ifdef HAVE_IOSTREAM
Packit Service c5cf8c
// Not all C++ compilers have iostream instead of iostream.h
Packit Service c5cf8c
#include <iostream>
Packit Service c5cf8c
#ifdef HAVE_NAMESPACE_STD
Packit Service c5cf8c
// Those that do often need the std namespace; otherwise, a bare "cout"
Packit Service c5cf8c
// is likely to fail to compile
Packit Service c5cf8c
using namespace std;
Packit Service c5cf8c
#endif
Packit Service c5cf8c
#else
Packit Service c5cf8c
#include <iostream.h>
Packit Service c5cf8c
#endif
Packit Service c5cf8c
#include <stdio.h>
Packit Service c5cf8c
#include "mpitestcxx.h"
Packit Service c5cf8c
#ifdef HAVE_STRING_H
Packit Service c5cf8c
#include <string.h>
Packit Service c5cf8c
#endif
Packit Service c5cf8c
Packit Service c5cf8c
/* #define DEBUG */
Packit Service c5cf8c
Packit Service c5cf8c
int test_communicators(void);
Packit Service c5cf8c
int copy_fn(const MPI::Comm &, int, void *, void *, void *, bool &);
Packit Service c5cf8c
int delete_fn(MPI::Comm &, int, void *, void *);
Packit Service c5cf8c
Packit Service c5cf8c
int main(int argc, char **argv)
Packit Service c5cf8c
{
Packit Service c5cf8c
    int errs = 0;
Packit Service c5cf8c
Packit Service c5cf8c
    MTest_Init();
Packit Service c5cf8c
Packit Service c5cf8c
    errs = test_communicators();
Packit Service c5cf8c
    MTest_Finalize(errs);
Packit Service c5cf8c
    return 0;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
int copy_fn(const MPI::Comm & oldcomm, int keyval, void *extra_state,
Packit Service c5cf8c
            void *attribute_val_in, void *attribute_val_out, bool & flag)
Packit Service c5cf8c
{
Packit Service c5cf8c
    /* Note that if (sizeof(int) < sizeof(void *), just setting the int
Packit Service c5cf8c
     * part of attribute_val_out may leave some dirty bits
Packit Service c5cf8c
     */
Packit Service c5cf8c
    *(MPI::Aint *) attribute_val_out = (MPI::Aint) attribute_val_in;
Packit Service c5cf8c
    flag = 1;
Packit Service c5cf8c
    return MPI::SUCCESS;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
int delete_fn(MPI::Comm & comm, int keyval, void *attribute_val, void *extra_state)
Packit Service c5cf8c
{
Packit Service c5cf8c
    int world_rank;
Packit Service c5cf8c
    world_rank = MPI::COMM_WORLD.Get_rank();
Packit Service c5cf8c
    if ((MPI::Aint) attribute_val != (MPI::Aint) world_rank) {
Packit Service c5cf8c
        cout << "incorrect attribute value " << *(int *) attribute_val << "\n";
Packit Service c5cf8c
        MPI::COMM_WORLD.Abort(1005);
Packit Service c5cf8c
    }
Packit Service c5cf8c
    return MPI::SUCCESS;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
int test_communicators(void)
Packit Service c5cf8c
{
Packit Service c5cf8c
    MPI::Intracomm dup_comm_world, lo_comm, rev_comm, dup_comm, split_comm, world_comm;
Packit Service c5cf8c
    MPI::Group world_group, lo_group, rev_group;
Packit Service c5cf8c
    void *vvalue;
Packit Service c5cf8c
    int ranges[1][3];
Packit Service c5cf8c
    int flag, world_rank, world_size, rank, size, n, key_1, key_3;
Packit Service c5cf8c
    int color, key, result;
Packit Service c5cf8c
    int errs = 0;
Packit Service c5cf8c
    MPI::Aint value;
Packit Service c5cf8c
Packit Service c5cf8c
    world_rank = MPI::COMM_WORLD.Get_rank();
Packit Service c5cf8c
    world_size = MPI::COMM_WORLD.Get_size();
Packit Service c5cf8c
#ifdef DEBUG
Packit Service c5cf8c
    if (world_rank == 0) {
Packit Service c5cf8c
        cout << "*** Communicators ***\n";
Packit Service c5cf8c
    }
Packit Service c5cf8c
#endif
Packit Service c5cf8c
Packit Service c5cf8c
    dup_comm_world = MPI::COMM_WORLD.Dup();
Packit Service c5cf8c
Packit Service c5cf8c
    /*
Packit Service c5cf8c
     * Exercise Comm_create by creating an equivalent to dup_comm_world
Packit Service c5cf8c
     * (sans attributes) and a half-world communicator.
Packit Service c5cf8c
     */
Packit Service c5cf8c
Packit Service c5cf8c
#ifdef DEBUG
Packit Service c5cf8c
    if (world_rank == 0) {
Packit Service c5cf8c
        cout << "    Comm_create\n";
Packit Service c5cf8c
    }
Packit Service c5cf8c
#endif
Packit Service c5cf8c
Packit Service c5cf8c
    world_group = dup_comm_world.Get_group();
Packit Service c5cf8c
    world_comm = dup_comm_world.Create(world_group);
Packit Service c5cf8c
    rank = world_comm.Get_rank();
Packit Service c5cf8c
    if (rank != world_rank) {
Packit Service c5cf8c
        errs++;
Packit Service c5cf8c
        cout << "incorrect rank in world comm: " << rank << "\n";
Packit Service c5cf8c
        MPI::COMM_WORLD.Abort(3001);
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    n = world_size / 2;
Packit Service c5cf8c
Packit Service c5cf8c
    ranges[0][0] = 0;
Packit Service c5cf8c
    ranges[0][1] = (world_size - n) - 1;
Packit Service c5cf8c
    ranges[0][2] = 1;
Packit Service c5cf8c
Packit Service c5cf8c
#ifdef DEBUG
Packit Service c5cf8c
    cout << "world rank = " << world_rank << " before range incl\n";
Packit Service c5cf8c
#endif
Packit Service c5cf8c
    lo_group = world_group.Range_incl(1, ranges);
Packit Service c5cf8c
#ifdef DEBUG
Packit Service c5cf8c
    cout << "world rank = " << world_rank << " after range incl\n";
Packit Service c5cf8c
#endif
Packit Service c5cf8c
    lo_comm = world_comm.Create(lo_group);
Packit Service c5cf8c
#ifdef DEBUG
Packit Service c5cf8c
    cout << "world rank = " << world_rank << " before group free\n";
Packit Service c5cf8c
#endif
Packit Service c5cf8c
    lo_group.Free();
Packit Service c5cf8c
Packit Service c5cf8c
#ifdef DEBUG
Packit Service c5cf8c
    cout << "world rank = " << world_rank << " after group free\n";
Packit Service c5cf8c
#endif
Packit Service c5cf8c
Packit Service c5cf8c
    if (world_rank < (world_size - n)) {
Packit Service c5cf8c
        rank = lo_comm.Get_rank();
Packit Service c5cf8c
        if (rank == MPI::UNDEFINED) {
Packit Service c5cf8c
            errs++;
Packit Service c5cf8c
            cout << "incorrect lo group rank: " << rank << "\n";
Packit Service c5cf8c
            MPI::COMM_WORLD.Abort(3002);
Packit Service c5cf8c
        } else {
Packit Service c5cf8c
            lo_comm.Barrier();
Packit Service c5cf8c
        }
Packit Service c5cf8c
    } else {
Packit Service c5cf8c
        if (lo_comm != MPI::COMM_NULL) {
Packit Service c5cf8c
            errs++;
Packit Service c5cf8c
            cout << "incorrect lo comm:\n";
Packit Service c5cf8c
            MPI::COMM_WORLD.Abort(3003);
Packit Service c5cf8c
        }
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
#ifdef DEBUG
Packit Service c5cf8c
    cout << "worldrank = " << world_rank << "\n";
Packit Service c5cf8c
#endif
Packit Service c5cf8c
    world_comm.Barrier();
Packit Service c5cf8c
Packit Service c5cf8c
#ifdef DEBUG
Packit Service c5cf8c
    cout << "bar!\n";
Packit Service c5cf8c
#endif
Packit Service c5cf8c
    /*
Packit Service c5cf8c
     * Check Comm_dup by adding attributes to lo_comm & duplicating
Packit Service c5cf8c
     */
Packit Service c5cf8c
#ifdef DEBUG
Packit Service c5cf8c
    if (world_rank == 0) {
Packit Service c5cf8c
        cout << "    Comm_dup\n";
Packit Service c5cf8c
    }
Packit Service c5cf8c
#endif
Packit Service c5cf8c
Packit Service c5cf8c
    if (lo_comm != MPI::COMM_NULL) {
Packit Service c5cf8c
        value = 9;
Packit Service c5cf8c
        key_1 = MPI::Comm::Create_keyval(copy_fn, delete_fn, &value);
Packit Service c5cf8c
        value = 8;
Packit Service c5cf8c
        value = 7;
Packit Service c5cf8c
        key_3 = MPI::Comm::Create_keyval(MPI::Comm::NULL_COPY_FN,
Packit Service c5cf8c
                                         MPI::Comm::NULL_DELETE_FN, &value);
Packit Service c5cf8c
Packit Service c5cf8c
        /* This may generate a compilation warning; it is, however, an
Packit Service c5cf8c
         * easy way to cache a value instead of a pointer */
Packit Service c5cf8c
        lo_comm.Set_attr(key_1, (void *) (MPI_Aint) world_rank);
Packit Service c5cf8c
        lo_comm.Set_attr(key_3, (void *) 0);
Packit Service c5cf8c
Packit Service c5cf8c
        dup_comm = lo_comm.Dup();
Packit Service c5cf8c
Packit Service c5cf8c
        /* Note that if sizeof(int) < sizeof(void *), we can't use
Packit Service c5cf8c
         * (void **)&value to get the value we passed into Attr_put.  To avoid
Packit Service c5cf8c
         * problems (e.g., alignment errors), we recover the value into
Packit Service c5cf8c
         * a (void *) and cast to int. Note that this may generate warning
Packit Service c5cf8c
         * messages from the compiler.  */
Packit Service c5cf8c
        flag = dup_comm.Get_attr(key_1, (void **) &vvalue);
Packit Service c5cf8c
        value = (MPI::Aint) vvalue;
Packit Service c5cf8c
Packit Service c5cf8c
        if (!flag) {
Packit Service c5cf8c
            errs++;
Packit Service c5cf8c
            cout << "dup_comm key_1 not found on " << world_rank << "\n";
Packit Service c5cf8c
            MPI::COMM_WORLD.Abort(3004);
Packit Service c5cf8c
        }
Packit Service c5cf8c
Packit Service c5cf8c
        if (value != world_rank) {
Packit Service c5cf8c
            errs++;
Packit Service c5cf8c
            cout << "dup_comm key_1 value incorrect: " << (long) value << "\n";
Packit Service c5cf8c
            MPI::COMM_WORLD.Abort(3005);
Packit Service c5cf8c
        }
Packit Service c5cf8c
Packit Service c5cf8c
        flag = dup_comm.Get_attr(key_3, (void **) &vvalue);
Packit Service c5cf8c
        if (flag) {
Packit Service c5cf8c
            errs++;
Packit Service c5cf8c
            cout << "dup_comm key_3 found!\n";
Packit Service c5cf8c
            MPI::COMM_WORLD.Abort(3008);
Packit Service c5cf8c
        }
Packit Service c5cf8c
        // Some C++ compilers (e.g., Solaris) refuse to
Packit Service c5cf8c
        // accept a straight cast to an int.
Packit Service c5cf8c
        // value = (MPI::Aint)vvalue;
Packit Service c5cf8c
        MPI::Comm::Free_keyval(key_1);
Packit Service c5cf8c
        MPI::Comm::Free_keyval(key_3);
Packit Service c5cf8c
    }
Packit Service c5cf8c
    /*
Packit Service c5cf8c
     * Split the world into even & odd communicators with reversed ranks.
Packit Service c5cf8c
     */
Packit Service c5cf8c
#ifdef DEBUG
Packit Service c5cf8c
    if (world_rank == 0) {
Packit Service c5cf8c
        cout << "    Comm_split\n";
Packit Service c5cf8c
    }
Packit Service c5cf8c
#endif
Packit Service c5cf8c
Packit Service c5cf8c
    color = world_rank % 2;
Packit Service c5cf8c
    key = world_size - world_rank;
Packit Service c5cf8c
Packit Service c5cf8c
    split_comm = dup_comm_world.Split(color, key);
Packit Service c5cf8c
    size = split_comm.Get_size();
Packit Service c5cf8c
    rank = split_comm.Get_rank();
Packit Service c5cf8c
    if (rank != ((size - world_rank / 2) - 1)) {
Packit Service c5cf8c
        errs++;
Packit Service c5cf8c
        cout << "incorrect split rank: " << rank << "\n";
Packit Service c5cf8c
        MPI::COMM_WORLD.Abort(3009);
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    split_comm.Barrier();
Packit Service c5cf8c
    /*
Packit Service c5cf8c
     * Test each possible Comm_compare result
Packit Service c5cf8c
     */
Packit Service c5cf8c
#ifdef DEBUG
Packit Service c5cf8c
    if (world_rank == 0) {
Packit Service c5cf8c
        cout << "    Comm_compare\n";
Packit Service c5cf8c
    }
Packit Service c5cf8c
#endif
Packit Service c5cf8c
Packit Service c5cf8c
    result = MPI::Comm::Compare(world_comm, world_comm);
Packit Service c5cf8c
    if (result != MPI::IDENT) {
Packit Service c5cf8c
        errs++;
Packit Service c5cf8c
        cout << "incorrect ident result: " << result << "\n";
Packit Service c5cf8c
        MPI::COMM_WORLD.Abort(3010);
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    if (lo_comm != MPI::COMM_NULL) {
Packit Service c5cf8c
        result = MPI::Comm::Compare(lo_comm, dup_comm);
Packit Service c5cf8c
        if (result != MPI::CONGRUENT) {
Packit Service c5cf8c
            errs++;
Packit Service c5cf8c
            cout << "incorrect congruent result: " << result << "\n";
Packit Service c5cf8c
            MPI::COMM_WORLD.Abort(3011);
Packit Service c5cf8c
        }
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    ranges[0][0] = world_size - 1;
Packit Service c5cf8c
    ranges[0][1] = 0;
Packit Service c5cf8c
    ranges[0][2] = -1;
Packit Service c5cf8c
Packit Service c5cf8c
    rev_group = world_group.Range_incl(1, ranges);
Packit Service c5cf8c
    rev_comm = world_comm.Create(rev_group);
Packit Service c5cf8c
Packit Service c5cf8c
    result = MPI::Comm::Compare(world_comm, rev_comm);
Packit Service c5cf8c
    if (result != MPI::SIMILAR && world_size != 1) {
Packit Service c5cf8c
        errs++;
Packit Service c5cf8c
        cout << "incorrect similar result: " << result << "\n";
Packit Service c5cf8c
        MPI::COMM_WORLD.Abort(3012);
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    if (lo_comm != MPI::COMM_NULL) {
Packit Service c5cf8c
        result = MPI::Comm::Compare(world_comm, lo_comm);
Packit Service c5cf8c
        if (result != MPI::UNEQUAL && world_size != 1) {
Packit Service c5cf8c
            errs++;
Packit Service c5cf8c
            cout << "incorrect unequal result: " << result << "\n";
Packit Service c5cf8c
            MPI::COMM_WORLD.Abort(3013);
Packit Service c5cf8c
        }
Packit Service c5cf8c
    }
Packit Service c5cf8c
    /*
Packit Service c5cf8c
     * Free all communicators created
Packit Service c5cf8c
     */
Packit Service c5cf8c
#ifdef DEBUG
Packit Service c5cf8c
    if (world_rank == 0)
Packit Service c5cf8c
        cout << "    Comm_free\n";
Packit Service c5cf8c
#endif
Packit Service c5cf8c
Packit Service c5cf8c
    world_comm.Free();
Packit Service c5cf8c
    dup_comm_world.Free();
Packit Service c5cf8c
Packit Service c5cf8c
    rev_comm.Free();
Packit Service c5cf8c
    split_comm.Free();
Packit Service c5cf8c
Packit Service c5cf8c
    world_group.Free();
Packit Service c5cf8c
    rev_group.Free();
Packit Service c5cf8c
Packit Service c5cf8c
    if (lo_comm != MPI::COMM_NULL) {
Packit Service c5cf8c
        lo_comm.Free();
Packit Service c5cf8c
        dup_comm.Free();
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    return errs;
Packit Service c5cf8c
}