Commit 51fdbedc authored by Xin Zhao's avatar Xin Zhao
Browse files

Add tests to test the atomicity for FOP, CAS and GACC operations.



The entire "read-modify-write" should be atomic for CAS, FOP and
GACC operations. This patch adds corresponding tests for them.
Signed-off-by: Pavan Balaji's avatarPavan Balaji <balaji@anl.gov>
parent bad898f9
......@@ -140,7 +140,10 @@ noinst_PROGRAMS = \
get-struct \
rput_local_comp \
racc_local_comp \
at_complete
at_complete \
atomic_rmw_fop \
atomic_rmw_cas \
atomic_rmw_gacc
if BUILD_MPIX_TESTS
noinst_PROGRAMS += aint
......
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
/*
*
* (C) 2015 by Argonne National Laboratory.
* See COPYRIGHT in top-level directory.
*/
/* This test is going to test the atomicity for "read-modify-write" in CAS
* operations */
/* There are three processes involved in this test: P0 (origin_shm), P1 (origin_am),
* and P2 (dest). P0 and P1 issues one CAS to P2 via SHM and AM respectively.
* For P0, origin value is 1 and compare value is 0; for P1, origin value is 0 and
* compare value is 1; for P2, initial target value is 0. The correct results can
* only be one of the following cases:
*
* (1) result value on P0: 0, result value on P1: 0, target value on P2: 1.
* (2) result value on P0: 0, result value on P1: 1, target value on P2: 0.
*
* All other results are not correct. */
#include "mpi.h"
#include <stdio.h>
#define LOOP_SIZE 10000
#define CHECK_TAG 123
int main (int argc, char *argv[]) {
int rank, size, i, j, k;
int errors = 0;
int origin_shm, origin_am, dest;
int *orig_buf = NULL, *result_buf = NULL, *compare_buf = NULL,
*target_buf = NULL, *check_buf = NULL;
MPI_Win win;
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
if (size != 3) {
/* run this test with three processes */
goto exit_test;
}
/* this works when MPIR_PARAM_CH3_ODD_EVEN_CLIQUES is set */
dest = 2;
origin_shm = 0;
origin_am = 1;
if (rank != dest) {
MPI_Alloc_mem(sizeof(int), MPI_INFO_NULL, &orig_buf);
MPI_Alloc_mem(sizeof(int), MPI_INFO_NULL, &result_buf);
MPI_Alloc_mem(sizeof(int), MPI_INFO_NULL, &compare_buf);
}
MPI_Win_allocate(sizeof(int), sizeof(int), MPI_INFO_NULL,
MPI_COMM_WORLD, &target_buf, &win);
for (k = 0; k < LOOP_SIZE; k++) {
/* init buffers */
if (rank == origin_shm) {
orig_buf[0] = 1;
compare_buf[0] = 0;
result_buf[0] = 0;
}
else if (rank == origin_am) {
orig_buf[0] = 0;
compare_buf[0] = 1;
result_buf[0] = 0;
}
else {
MPI_Win_lock(MPI_LOCK_SHARED, rank, 0, win);
target_buf[0] = 0;
MPI_Win_unlock(rank, win);
}
MPI_Barrier(MPI_COMM_WORLD);
/* perform FOP */
MPI_Win_lock_all(0, win);
if (rank != dest) {
MPI_Compare_and_swap(orig_buf, compare_buf, result_buf, MPI_INT, dest, 0, win);
MPI_Win_flush(dest, win);
}
MPI_Win_unlock_all(win);
MPI_Barrier(MPI_COMM_WORLD);
/* check results */
if (rank != dest) {
MPI_Gather(result_buf, 1, MPI_INT, check_buf, 1, MPI_INT, dest, MPI_COMM_WORLD);
}
else {
MPI_Alloc_mem(sizeof(int) * 3, MPI_INFO_NULL, &check_buf);
MPI_Gather(target_buf, 1, MPI_INT, check_buf, 1, MPI_INT, dest, MPI_COMM_WORLD);
if (!(check_buf[dest] == 0 && check_buf[origin_shm] == 0 && check_buf[origin_am] == 1) &&
!(check_buf[dest] == 1 && check_buf[origin_shm] == 0 && check_buf[origin_am] == 0)) {
printf("Wrong results: target result = %d, origin_shm result = %d, origin_am result = %d\n",
check_buf[dest], check_buf[origin_shm], check_buf[origin_am]);
printf("Expected results (1): target result = 1, origin_shm result = 0, origin_am result = 0\n");
printf("Expected results (2): target result = 0, origin_shm result = 0, origin_am result = 1\n");
errors++;
}
MPI_Free_mem(check_buf);
}
}
MPI_Win_free(&win);
if (rank == origin_am || rank == origin_shm) {
MPI_Free_mem(orig_buf);
MPI_Free_mem(result_buf);
MPI_Free_mem(compare_buf);
}
exit_test:
if (rank == dest && errors == 0)
printf(" No Errors\n");
MPI_Finalize();
return 0;
}
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
/*
*
* (C) 2015 by Argonne National Laboratory.
* See COPYRIGHT in top-level directory.
*/
/* This test is going to test the atomicity for "read-modify-write" in FOP
* operations */
/* There are three processes involved in this test: P0 (origin_shm), P1 (origin_am),
* and P2 (dest). P0 and P1 issues multiple FOP with MPI_SUM and integer (value 1)
* to P2 via SHM and AM respectively. The correct results should be that the
* results on P0 and P1 never be the same. */
#include "mpi.h"
#include <stdio.h>
#define AM_BUF_SIZE 10
#define SHM_BUF_SIZE 1000
#define WIN_BUF_SIZE 1
#define LOOP_SIZE 15
#define CHECK_TAG 123
int main (int argc, char *argv[]) {
int rank, size, i, j, k;
int errors = 0, all_errors = 0;
int origin_shm, origin_am, dest;
int my_buf_size;
int *orig_buf = NULL, *result_buf = NULL, *target_buf = NULL, *check_buf = NULL;
MPI_Win win;
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
if (size != 3) {
/* run this test with three processes */
goto exit_test;
}
/* this works when MPIR_PARAM_CH3_ODD_EVEN_CLIQUES is set */
dest = 2;
origin_shm = 0;
origin_am = 1;
if (rank == origin_am) my_buf_size = AM_BUF_SIZE;
else if (rank == origin_shm) my_buf_size = SHM_BUF_SIZE;
if (rank != dest) {
MPI_Alloc_mem(sizeof(int) * my_buf_size, MPI_INFO_NULL, &orig_buf);
MPI_Alloc_mem(sizeof(int) * my_buf_size, MPI_INFO_NULL, &result_buf);
}
MPI_Win_allocate(sizeof(int) * WIN_BUF_SIZE, sizeof(int), MPI_INFO_NULL,
MPI_COMM_WORLD, &target_buf, &win);
for (k = 0; k < LOOP_SIZE; k++) {
/* init buffers */
if (rank != dest) {
for (i = 0; i < my_buf_size; i++) {orig_buf[i] = 1; result_buf[i] = 0;}
}
else {
MPI_Win_lock(MPI_LOCK_SHARED, rank, 0, win);
for (i = 0; i < WIN_BUF_SIZE; i++) {target_buf[i] = 0;}
MPI_Win_unlock(rank, win);
}
MPI_Barrier(MPI_COMM_WORLD);
/* perform FOP */
MPI_Win_lock_all(0, win);
if (rank != dest) {
for (i = 0; i < my_buf_size; i++) {
MPI_Fetch_and_op(&(orig_buf[i]), &(result_buf[i]), MPI_INT, dest, 0, MPI_SUM, win);
MPI_Win_flush(dest, win);
}
}
MPI_Win_unlock_all(win);
MPI_Barrier(MPI_COMM_WORLD);
if (rank != dest) {
/* check results on P0 and P2 (origin) */
if (rank == origin_am) {
MPI_Send(result_buf, AM_BUF_SIZE, MPI_INT, origin_shm, CHECK_TAG, MPI_COMM_WORLD);
}
else if (rank == origin_shm) {
MPI_Alloc_mem(sizeof(int) * AM_BUF_SIZE, MPI_INFO_NULL, &check_buf);
MPI_Recv(check_buf, AM_BUF_SIZE, MPI_INT, origin_am, CHECK_TAG, MPI_COMM_WORLD, &status);
for (i = 0; i < AM_BUF_SIZE; i++) {
for (j = 0; j < SHM_BUF_SIZE; j++) {
if (check_buf[i] == result_buf[j]) {
printf("LOOP=%d, rank=%d, FOP, both check_buf[%d] and result_buf[%d] equal to %d, expected to be different. \n",
k, rank, i, j, check_buf[i]);
errors++;
}
}
}
MPI_Free_mem(check_buf);
}
}
else {
/* check results on P1 */
if (target_buf[0] != AM_BUF_SIZE + SHM_BUF_SIZE) {
printf("LOOP=%d, rank=%d, FOP, target_buf[0] = %d, expected %d. \n",
k, rank, target_buf[0], AM_BUF_SIZE+SHM_BUF_SIZE);
errors++;
}
}
}
MPI_Win_free(&win);
if (rank == origin_am || rank == origin_shm) {
MPI_Free_mem(orig_buf);
MPI_Free_mem(result_buf);
}
exit_test:
MPI_Reduce(&errors, &all_errors, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);
if (rank == 0 && all_errors == 0)
printf(" No Errors\n");
MPI_Finalize();
return 0;
}
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
/*
*
* (C) 2015 by Argonne National Laboratory.
* See COPYRIGHT in top-level directory.
*/
/* This test is going to test the atomicity for "read-modify-write" in GACC
* operations */
/* This test is similiar with atomic_rmw_fop.c.
* There are three processes involved in this test: P0 (origin_shm), P1 (origin_am),
* and P2 (dest). P0 and P1 issues multiple GACC with MPI_SUM and OP_COUNT integers
* (value 1) to P2 via SHM and AM respectively. The correct results should be that the
* results on P0 and P1 never be the same for intergers on the corresponding index
* in [0...OP_COUNT-1].
*/
#include "mpi.h"
#include <stdio.h>
#define OP_COUNT 10
#define AM_BUF_NUM 10
#define SHM_BUF_NUM 10000
#define WIN_BUF_NUM 1
#define LOOP_SIZE 15
#define CHECK_TAG 123
int rank, size;
int dest, origin_shm, origin_am;
int *orig_buf = NULL, *result_buf = NULL, *target_buf = NULL, *check_buf = NULL;
void checkResults(int loop_k, int *errors) {
int i, j, m;
MPI_Status status;
if (rank != dest) {
/* check results on P0 and P2 (origin) */
if (rank == origin_am) {
MPI_Send(result_buf, AM_BUF_NUM * OP_COUNT, MPI_INT, origin_shm, CHECK_TAG, MPI_COMM_WORLD);
}
else if (rank == origin_shm) {
MPI_Alloc_mem(sizeof(int) * AM_BUF_NUM * OP_COUNT, MPI_INFO_NULL, &check_buf);
MPI_Recv(check_buf, AM_BUF_NUM * OP_COUNT, MPI_INT, origin_am, CHECK_TAG, MPI_COMM_WORLD, &status);
for (i = 0; i < AM_BUF_NUM; i++) {
for (j = 0; j < SHM_BUF_NUM; j++) {
for (m = 0; m < OP_COUNT; m++) {
if (check_buf[i*OP_COUNT+m] == result_buf[j*OP_COUNT+m]) {
printf("LOOP=%d, rank=%d, FOP, both check_buf[%d] and result_buf[%d] equal to %d, expected to be different. \n",
loop_k, rank, i*OP_COUNT+m, j*OP_COUNT+m, check_buf[i*OP_COUNT+m]);
(*errors)++;
}
}
}
}
MPI_Free_mem(check_buf);
}
}
else {
/* check results on P1 */
for (i = 0; i < OP_COUNT; i++) {
if (target_buf[i] != AM_BUF_NUM + SHM_BUF_NUM) {
printf("LOOP=%d, rank=%d, FOP, target_buf[%d] = %d, expected %d. \n",
loop_k, rank, i, target_buf[i], AM_BUF_NUM+SHM_BUF_NUM);
(*errors)++;
}
}
}
}
int main (int argc, char *argv[]) {
int i, j, k;
int errors = 0, all_errors = 0;
int my_buf_num;
MPI_Win win;
MPI_Datatype origin_dtp, target_dtp;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
if (size != 3) {
/* run this test with three processes */
goto exit_test;
}
MPI_Type_contiguous(OP_COUNT, MPI_INT, &origin_dtp);
MPI_Type_commit(&origin_dtp);
MPI_Type_contiguous(OP_COUNT, MPI_INT, &target_dtp);
MPI_Type_commit(&target_dtp);
/* this works when MPIR_PARAM_CH3_ODD_EVEN_CLIQUES is set */
dest = 2;
origin_shm = 0;
origin_am = 1;
if (rank == origin_am) my_buf_num = AM_BUF_NUM;
else if (rank == origin_shm) my_buf_num = SHM_BUF_NUM;
if (rank != dest) {
MPI_Alloc_mem(sizeof(int) * my_buf_num * OP_COUNT, MPI_INFO_NULL, &orig_buf);
MPI_Alloc_mem(sizeof(int) * my_buf_num * OP_COUNT, MPI_INFO_NULL, &result_buf);
}
MPI_Win_allocate(sizeof(int) * WIN_BUF_NUM * OP_COUNT, sizeof(int), MPI_INFO_NULL,
MPI_COMM_WORLD, &target_buf, &win);
for (k = 0; k < LOOP_SIZE; k++) {
/* ====== Part 1: test basic datatypes ======== */
/* init buffers */
if (rank != dest) {
for (i = 0; i < my_buf_num * OP_COUNT; i++) {orig_buf[i] = 1; result_buf[i] = 0;}
}
else {
MPI_Win_lock(MPI_LOCK_SHARED, rank, 0, win);
for (i = 0; i < WIN_BUF_NUM * OP_COUNT; i++) {target_buf[i] = 0;}
MPI_Win_unlock(rank, win);
}
MPI_Barrier(MPI_COMM_WORLD);
MPI_Win_lock_all(0, win);
if (rank != dest) {
for (i = 0; i < my_buf_num; i++) {
MPI_Get_accumulate(&(orig_buf[i*OP_COUNT]), OP_COUNT, MPI_INT,
&(result_buf[i*OP_COUNT]), OP_COUNT, MPI_INT,
dest, 0, OP_COUNT, MPI_INT, MPI_SUM, win);
MPI_Win_flush(dest, win);
}
}
MPI_Win_unlock_all(win);
MPI_Barrier(MPI_COMM_WORLD);
checkResults(k, &errors);
/* ====== Part 2: test derived datatypes (origin derived, target derived) ======== */
/* init buffers */
if (rank != dest) {
for (i = 0; i < my_buf_num * OP_COUNT; i++) {orig_buf[i] = 1; result_buf[i] = 0;}
}
else {
MPI_Win_lock(MPI_LOCK_SHARED, rank, 0, win);
for (i = 0; i < WIN_BUF_NUM * OP_COUNT; i++) {target_buf[i] = 0;}
MPI_Win_unlock(rank, win);
}
MPI_Win_lock_all(0, win);
if (rank != dest) {
for (i = 0; i < my_buf_num; i++) {
MPI_Get_accumulate(&(orig_buf[i*OP_COUNT]), 1, origin_dtp,
&(result_buf[i*OP_COUNT]), 1, origin_dtp,
dest, 0, 1, target_dtp, MPI_SUM, win);
MPI_Win_flush(dest, win);
}
}
MPI_Win_unlock_all(win);
MPI_Barrier(MPI_COMM_WORLD);
checkResults(k, &errors);
/* ====== Part 3: test derived datatypes (origin basic, target derived) ======== */
/* init buffers */
if (rank != dest) {
for (i = 0; i < my_buf_num * OP_COUNT; i++) {orig_buf[i] = 1; result_buf[i] = 0;}
}
else {
MPI_Win_lock(MPI_LOCK_SHARED, rank, 0, win);
for (i = 0; i < WIN_BUF_NUM * OP_COUNT; i++) {target_buf[i] = 0;}
MPI_Win_unlock(rank, win);
}
MPI_Win_lock_all(0, win);
if (rank != dest) {
for (i = 0; i < my_buf_num; i++) {
MPI_Get_accumulate(&(orig_buf[i*OP_COUNT]), OP_COUNT, MPI_INT,
&(result_buf[i*OP_COUNT]), OP_COUNT, MPI_INT,
dest, 0, 1, target_dtp, MPI_SUM, win);
MPI_Win_flush(dest, win);
}
}
MPI_Win_unlock_all(win);
MPI_Barrier(MPI_COMM_WORLD);
checkResults(k, &errors);
/* ====== Part 4: test derived datatypes (origin derived target basic) ======== */
/* init buffers */
if (rank != dest) {
for (i = 0; i < my_buf_num * OP_COUNT; i++) {orig_buf[i] = 1; result_buf[i] = 0;}
}
else {
MPI_Win_lock(MPI_LOCK_SHARED, rank, 0, win);
for (i = 0; i < WIN_BUF_NUM * OP_COUNT; i++) {target_buf[i] = 0;}
MPI_Win_unlock(rank, win);
}
MPI_Win_lock_all(0, win);
if (rank != dest) {
for (i = 0; i < my_buf_num; i++) {
MPI_Get_accumulate(&(orig_buf[i*OP_COUNT]), 1, origin_dtp,
&(result_buf[i*OP_COUNT]), 1, origin_dtp,
dest, 0, OP_COUNT, MPI_INT, MPI_SUM, win);
MPI_Win_flush(dest, win);
}
}
MPI_Win_unlock_all(win);
MPI_Barrier(MPI_COMM_WORLD);
checkResults(k, &errors);
}
MPI_Win_free(&win);
if (rank == origin_am || rank == origin_shm) {
MPI_Free_mem(orig_buf);
MPI_Free_mem(result_buf);
}
MPI_Type_free(&origin_dtp);
MPI_Type_free(&target_dtp);
exit_test:
MPI_Reduce(&errors, &all_errors, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);
if (rank == 0 && all_errors == 0)
printf(" No Errors\n");
MPI_Finalize();
return 0;
}
......@@ -128,6 +128,9 @@ win_shared_zerobyte 4 mpiversion=3.0
win_shared_put_flush_get 4 mpiversion=3.0
get-struct 2
at_complete 2
atomic_rmw_fop 3
atomic_rmw_cas 3
atomic_rmw_gacc 3
@mpix@ aint 2 strict=false
## This test is not strictly correct. This was meant to test out the
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment