|
Packit |
0848f5 |
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
|
|
Packit |
0848f5 |
/*
|
|
Packit |
0848f5 |
*
|
|
Packit |
0848f5 |
* (C) 2015 by Argonne National Laboratory.
|
|
Packit |
0848f5 |
* See COPYRIGHT in top-level directory.
|
|
Packit |
0848f5 |
*/
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#include <stdio.h>
|
|
Packit |
0848f5 |
#include <stdlib.h>
|
|
Packit |
0848f5 |
#include <mpi.h>
|
|
Packit |
0848f5 |
#include "mpitest.h"
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#define ITER 10000
|
|
Packit |
0848f5 |
#define BUF_CNT 1
|
|
Packit |
0848f5 |
int local_buf[BUF_CNT], result_addr[BUF_CNT];
|
|
Packit |
0848f5 |
#ifdef TEST_CAS
|
|
Packit |
0848f5 |
int compare_buf[BUF_CNT];
|
|
Packit |
0848f5 |
#endif
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
const int verbose = 0;
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* This test checks the remote completion of flush with RMA write-like operations
|
|
Packit |
0848f5 |
* (PUT, ACC, GET_ACC, FOP, CAS), and confirms result by shm load.
|
|
Packit |
0848f5 |
* 1. P(target) and P(checker) allocate a shared window, and
|
|
Packit |
0848f5 |
* then create a global window with P(origin) by using the shared window buffer.
|
|
Packit |
0848f5 |
* 2. P(origin) issues RMA operations and flush to P(target) through the global
|
|
Packit |
0848f5 |
* window and then call send-recv to synchronize with P(checker).
|
|
Packit |
0848f5 |
* 3. P(checker) then checks the result through shm window by local load. */
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
int rank = -1, nproc = 0;
|
|
Packit |
0848f5 |
int origin = -1, target = -1, checker = -1;
|
|
Packit |
0848f5 |
MPI_Win win = MPI_WIN_NULL, shm_win = MPI_WIN_NULL;
|
|
Packit |
0848f5 |
int *shm_target_base = NULL, *my_base = NULL;
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* Define operation name for error message */
|
|
Packit |
0848f5 |
#ifdef TEST_PUT
|
|
Packit |
0848f5 |
const char *rma_name = "Put";
|
|
Packit |
0848f5 |
#elif defined(TEST_ACC)
|
|
Packit |
0848f5 |
const char *rma_name = "Accumulate";
|
|
Packit |
0848f5 |
#elif defined(TEST_GACC)
|
|
Packit |
0848f5 |
const char *rma_name = "Get_accumulate";
|
|
Packit |
0848f5 |
#elif defined(TEST_FOP)
|
|
Packit |
0848f5 |
const char *rma_name = "Fetch_and_op";
|
|
Packit |
0848f5 |
#elif defined(TEST_CAS)
|
|
Packit |
0848f5 |
const char *rma_name = "Compare_and_swap";
|
|
Packit |
0848f5 |
#else
|
|
Packit |
0848f5 |
const char *rma_name = "None";
|
|
Packit |
0848f5 |
#endif
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* Issue functions for different RMA operations */
|
|
Packit |
0848f5 |
#ifdef TEST_PUT
|
|
Packit |
0848f5 |
static inline void issue_rma_op(int i)
|
|
Packit |
0848f5 |
{
|
|
Packit |
0848f5 |
MPI_Put(&local_buf[i], 1, MPI_INT, target, i, 1, MPI_INT, win);
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
#elif defined(TEST_ACC)
|
|
Packit |
0848f5 |
static inline void issue_rma_op(int i)
|
|
Packit |
0848f5 |
{
|
|
Packit |
0848f5 |
MPI_Accumulate(&local_buf[i], 1, MPI_INT, target, i, 1, MPI_INT, MPI_REPLACE, win);
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
#elif defined(TEST_GACC)
|
|
Packit |
0848f5 |
static inline void issue_rma_op(int i)
|
|
Packit |
0848f5 |
{
|
|
Packit |
0848f5 |
MPI_Get_accumulate(&local_buf[i], 1, MPI_INT, &result_addr[i], 1, MPI_INT, target, i,
|
|
Packit |
0848f5 |
1, MPI_INT, MPI_REPLACE, win);
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
#elif defined(TEST_FOP)
|
|
Packit |
0848f5 |
static inline void issue_rma_op(int i)
|
|
Packit |
0848f5 |
{
|
|
Packit |
0848f5 |
MPI_Fetch_and_op(&local_buf[i], &result_addr[i], MPI_INT, target, i, MPI_REPLACE, win);
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
#elif defined(TEST_CAS)
|
|
Packit |
0848f5 |
static inline void issue_rma_op(int i)
|
|
Packit |
0848f5 |
{
|
|
Packit |
0848f5 |
compare_buf[i] = i; /* always equal to window value, thus swap happens */
|
|
Packit |
0848f5 |
MPI_Compare_and_swap(&local_buf[i], &compare_buf[i], &result_addr[i], MPI_INT, target, i, win);
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
#endif
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* Local check function for GET-like operations */
|
|
Packit |
0848f5 |
#if defined(TEST_GACC) || defined(TEST_FOP) || defined(TEST_CAS)
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* Check local result buffer for GET-like operations */
|
|
Packit |
0848f5 |
static int check_local_result(int iter)
|
|
Packit |
0848f5 |
{
|
|
Packit |
0848f5 |
int i = 0;
|
|
Packit |
0848f5 |
int errors = 0;
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
for (i = 0; i < BUF_CNT; i++) {
|
|
Packit |
0848f5 |
if (result_addr[i] != i) {
|
|
Packit |
0848f5 |
printf("rank %d (iter %d) - check %s, got result_addr[%d] = %d, expected %d\n",
|
|
Packit |
0848f5 |
rank, iter, rma_name, i, result_addr[i], i);
|
|
Packit |
0848f5 |
errors++;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
return errors;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#else
|
|
Packit |
0848f5 |
#define check_local_result(iter) (0)
|
|
Packit |
0848f5 |
#endif
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
static int run_test()
|
|
Packit |
0848f5 |
{
|
|
Packit |
0848f5 |
int i = 0, x = 0;
|
|
Packit |
0848f5 |
int errors = 0;
|
|
Packit |
0848f5 |
int sbuf = 0, rbuf = 0;
|
|
Packit |
0848f5 |
MPI_Status stat;
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
for (x = 0; x < ITER; x++) {
|
|
Packit |
0848f5 |
/* 1. Target resets window data */
|
|
Packit |
0848f5 |
if (rank == target) {
|
|
Packit |
0848f5 |
for (i = 0; i < BUF_CNT; i++)
|
|
Packit |
0848f5 |
my_base[i] = i;
|
|
Packit |
0848f5 |
MPI_Win_sync(shm_win); /* write is done on shm window */
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
MPI_Barrier(MPI_COMM_WORLD);
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* 2. Every one resets local data */
|
|
Packit |
0848f5 |
for (i = 0; i < BUF_CNT; i++) {
|
|
Packit |
0848f5 |
local_buf[i] = BUF_CNT + x * BUF_CNT + i;
|
|
Packit |
0848f5 |
result_addr[i] = 0;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* 3. Origin issues RMA operation to target */
|
|
Packit |
0848f5 |
if (rank == origin) {
|
|
Packit |
0848f5 |
/* 3-1. Issue RMA. */
|
|
Packit |
0848f5 |
for (i = 0; i < BUF_CNT; i++) {
|
|
Packit |
0848f5 |
issue_rma_op(i);
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
MPI_Win_flush(target, win);
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* 3-2. Check local result buffer. */
|
|
Packit |
0848f5 |
errors += check_local_result(x);
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* sync with checker */
|
|
Packit |
0848f5 |
MPI_Send(&sbuf, 1, MPI_INT, checker, 999, MPI_COMM_WORLD);
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* 4. Checker confirms result on target */
|
|
Packit |
0848f5 |
if (rank == checker) {
|
|
Packit |
0848f5 |
/* sync with origin */
|
|
Packit |
0848f5 |
MPI_Recv(&rbuf, 1, MPI_INT, origin, 999, MPI_COMM_WORLD, &stat;;
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
MPI_Win_sync(shm_win);
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
for (i = 0; i < BUF_CNT; i++) {
|
|
Packit |
0848f5 |
if (shm_target_base[i] != local_buf[i]) {
|
|
Packit |
0848f5 |
printf("rank %d (iter %d) - check %s, got shm_target_base[%d] = %d, "
|
|
Packit |
0848f5 |
"expected %d\n", rank, x, rma_name, i, shm_target_base[i], local_buf[i]);
|
|
Packit |
0848f5 |
errors++;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
MPI_Barrier(MPI_COMM_WORLD);
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
return errors;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
int main(int argc, char *argv[])
|
|
Packit |
0848f5 |
{
|
|
Packit |
0848f5 |
int i;
|
|
Packit |
0848f5 |
int errors = 0, all_errors = 0;
|
|
Packit |
0848f5 |
MPI_Comm shm_comm = MPI_COMM_NULL;
|
|
Packit |
0848f5 |
int shm_rank;
|
|
Packit |
0848f5 |
int *shm_ranks = NULL, *shm_root_ranks = NULL;
|
|
Packit |
0848f5 |
int win_size = sizeof(int) * BUF_CNT;
|
|
Packit |
0848f5 |
int win_unit = sizeof(int);
|
|
Packit |
0848f5 |
int shm_root_rank = -1, shm_target = -1, target_shm_root = -1;
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
MPI_Init(&argc, &argv);
|
|
Packit |
0848f5 |
MPI_Comm_rank(MPI_COMM_WORLD, &rank;;
|
|
Packit |
0848f5 |
MPI_Comm_size(MPI_COMM_WORLD, &nproc);
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
if (nproc != 3) {
|
|
Packit |
0848f5 |
if (rank == 0)
|
|
Packit |
0848f5 |
printf("Error: must be run with three processes\n");
|
|
Packit |
0848f5 |
MPI_Barrier(MPI_COMM_WORLD);
|
|
Packit |
0848f5 |
MPI_Abort(MPI_COMM_WORLD, 1);
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#if !defined(TEST_PUT) && !defined(TEST_ACC) && !defined(TEST_GACC) && !defined(TEST_FOP) && !defined(TEST_CAS)
|
|
Packit |
0848f5 |
if (rank == 0)
|
|
Packit |
0848f5 |
printf("Error: must specify operation type at compile time\n");
|
|
Packit |
0848f5 |
MPI_Barrier(MPI_COMM_WORLD);
|
|
Packit |
0848f5 |
MPI_Abort(MPI_COMM_WORLD, 1);
|
|
Packit |
0848f5 |
#endif
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
MPI_Comm_split_type(MPI_COMM_WORLD, MPI_COMM_TYPE_SHARED, rank, MPI_INFO_NULL, &shm_comm);
|
|
Packit |
0848f5 |
MPI_Comm_rank(shm_comm, &shm_rank);
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
shm_ranks = (int *) calloc(nproc, sizeof(int));
|
|
Packit |
0848f5 |
shm_root_ranks = (int *) calloc(nproc, sizeof(int));
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* Identify node id */
|
|
Packit |
0848f5 |
if (shm_rank == 0)
|
|
Packit |
0848f5 |
shm_root_rank = rank;
|
|
Packit |
0848f5 |
MPI_Bcast(&shm_root_rank, 1, MPI_INT, 0, shm_comm);
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* Exchange local root rank and local rank */
|
|
Packit |
0848f5 |
shm_ranks[rank] = shm_rank;
|
|
Packit |
0848f5 |
shm_root_ranks[rank] = shm_root_rank;
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
MPI_Allgather(MPI_IN_PLACE, 0, MPI_DATATYPE_NULL, shm_ranks, 1, MPI_INT, MPI_COMM_WORLD);
|
|
Packit |
0848f5 |
MPI_Allgather(MPI_IN_PLACE, 0, MPI_DATATYPE_NULL, shm_root_ranks, 1, MPI_INT, MPI_COMM_WORLD);
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* Check if there are at least two processes in shared memory. */
|
|
Packit |
0848f5 |
for (i = 0; i < nproc; i++) {
|
|
Packit |
0848f5 |
if (shm_ranks[i] != 0) {
|
|
Packit |
0848f5 |
target_shm_root = shm_root_ranks[i];
|
|
Packit |
0848f5 |
break;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* Every process is in separate memory, we cannot create shared window. Just return. */
|
|
Packit |
0848f5 |
if (target_shm_root < 0)
|
|
Packit |
0848f5 |
goto exit;
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* Identify origin, target and checker ranks.
|
|
Packit |
0848f5 |
* the first process in shared memory is target, and the second one is checker;
|
|
Packit |
0848f5 |
* the last process is origin.*/
|
|
Packit |
0848f5 |
shm_target = 0;
|
|
Packit |
0848f5 |
for (i = 0; i < nproc; i++) {
|
|
Packit |
0848f5 |
if (shm_root_ranks[i] == target_shm_root) {
|
|
Packit |
0848f5 |
if (shm_ranks[i] == 0) {
|
|
Packit |
0848f5 |
target = i;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
else if (shm_ranks[i] == 1) {
|
|
Packit |
0848f5 |
checker = i;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
else {
|
|
Packit |
0848f5 |
/* all three processes are in shared memory, origin is the third one. */
|
|
Packit |
0848f5 |
origin = i;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
else {
|
|
Packit |
0848f5 |
/* origin is in separate memory. */
|
|
Packit |
0848f5 |
origin = i;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
if (verbose) {
|
|
Packit |
0848f5 |
printf("---- rank %d: origin = %d, checker = %d, target = %d, test %s\n",
|
|
Packit |
0848f5 |
rank, origin, checker, target, rma_name);
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* Allocate shared memory among local processes, then create a global window
|
|
Packit |
0848f5 |
* with the shared window buffers. */
|
|
Packit |
0848f5 |
MPI_Win_allocate_shared(win_size, win_unit, MPI_INFO_NULL, shm_comm, &my_base, &shm_win);
|
|
Packit |
0848f5 |
MPI_Win_create(my_base, win_size, win_unit, MPI_INFO_NULL, MPI_COMM_WORLD, &win);
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* Get address of target window on checker process. */
|
|
Packit |
0848f5 |
if (rank == checker) {
|
|
Packit |
0848f5 |
MPI_Aint size;
|
|
Packit |
0848f5 |
int disp_unit;
|
|
Packit |
0848f5 |
MPI_Win_shared_query(shm_win, shm_target, &size, &disp_unit, &shm_target_base);
|
|
Packit |
0848f5 |
if (verbose) {
|
|
Packit |
0848f5 |
printf("---- I am checker = %d, shm_target_base=%p\n", checker, shm_target_base);
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* Start checking. */
|
|
Packit |
0848f5 |
MPI_Win_lock_all(0, win);
|
|
Packit |
0848f5 |
MPI_Win_lock_all(0, shm_win);
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
errors = run_test();
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
MPI_Win_unlock_all(shm_win);
|
|
Packit |
0848f5 |
MPI_Win_unlock_all(win);
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
MPI_Reduce(&errors, &all_errors, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
exit:
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
if (rank == 0 && all_errors == 0)
|
|
Packit |
0848f5 |
printf(" No Errors\n");
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
if (shm_ranks)
|
|
Packit |
0848f5 |
free(shm_ranks);
|
|
Packit |
0848f5 |
if (shm_root_ranks)
|
|
Packit |
0848f5 |
free(shm_root_ranks);
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
if (shm_win != MPI_WIN_NULL)
|
|
Packit |
0848f5 |
MPI_Win_free(&shm_win);
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
if (win != MPI_WIN_NULL)
|
|
Packit |
0848f5 |
MPI_Win_free(&win);
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
if (shm_comm != MPI_COMM_NULL)
|
|
Packit |
0848f5 |
MPI_Comm_free(&shm_comm);
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
MPI_Finalize();
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
return 0;
|
|
Packit |
0848f5 |
}
|