1 /*
2  * Copyright (C) by Argonne National Laboratory
3  *     See COPYRIGHT in top-level directory
4  */
5 
6 /* This test is going to test atomic GET (GACC/FOP+MPI_NO_OP).
7  *
8  * There are totally three processes involved in this test. Both
9  * rank 1 and rank 2 issue RMA operations to rank 0. Rank 2 issues
10  * atomic PUT (ACC+MPI_REPLACE), whereas rank 1 issues atomic
11  * GET (GACC/FOP+MPI_NO_OP). The datatype used in the test is
12  * pair-type. The initial value of pair-type data in origin buffer
13  * of atomic PUT is set so that the two basic values equal with
14  * each other. Due to the atomicity of GET, the expected resulting
15  * data should also have equivalent basic values. */
16 
17 #include "mpi.h"
18 #include <stdio.h>
19 #include "mpitest.h"
20 
21 #define LOOP 100
22 #define DATA_SIZE 100
23 #define OPS_NUM 10000
24 #define GACC_SZ 10
25 
26 #if defined(TEST_SHORT_INT)
27 #define MTEST_PAIRTYPE_A short
28 #define MTEST_MPI_PAIRTYPE MPI_SHORT_INT
29 #define MTEST_PAIRTYPE_A_STRFMT "%hd"
30 
31 #elif defined(TEST_2INT)
32 #define MTEST_PAIRTYPE_A int
33 #define MTEST_MPI_PAIRTYPE MPI_2INT
34 #define MTEST_PAIRTYPE_A_STRFMT "%d"
35 
36 #elif defined(TEST_LONG_INT)
37 #define MTEST_PAIRTYPE_A long
38 #define MTEST_MPI_PAIRTYPE MPI_LONG_INT
39 #define MTEST_PAIRTYPE_A_STRFMT "%ld"
40 
41 #elif defined(TEST_FLOAT_INT)
42 #define MTEST_PAIRTYPE_A float
43 #define MTEST_MPI_PAIRTYPE MPI_FLOAT_INT
44 #define MTEST_PAIRTYPE_A_STRFMT "%f"
45 
46 #elif defined(TEST_DOUBLE_INT)
47 #define MTEST_PAIRTYPE_A double
48 #define MTEST_MPI_PAIRTYPE MPI_DOUBLE_INT
49 #define MTEST_PAIRTYPE_A_STRFMT "%lf"
50 
51 #else
52 #define MTEST_PAIRTYPE_A long double
53 #define MTEST_MPI_PAIRTYPE MPI_LONG_DOUBLE_INT
54 #define MTEST_PAIRTYPE_A_STRFMT "%Lf"
55 #endif
56 
57 typedef struct pair_struct {
58     MTEST_PAIRTYPE_A a;
59     int b;
60 } pair_struct_t;
61 
main(int argc,char * argv[])62 int main(int argc, char *argv[])
63 {
64     int rank, nproc;
65     int i, j, k;
66     int errs = 0, curr_errors = 0;
67     MPI_Win win;
68     pair_struct_t *tar_buf = NULL;
69     pair_struct_t *orig_buf = NULL;
70     pair_struct_t *result_buf = NULL;
71 
72     /* This test needs to work with 3 processes. */
73 
74     MTest_Init(&argc, &argv);
75 
76     MPI_Comm_size(MPI_COMM_WORLD, &nproc);
77     MPI_Comm_rank(MPI_COMM_WORLD, &rank);
78 
79     MPI_Alloc_mem(sizeof(pair_struct_t) * DATA_SIZE, MPI_INFO_NULL, &orig_buf);
80     MPI_Alloc_mem(sizeof(pair_struct_t) * DATA_SIZE, MPI_INFO_NULL, &result_buf);
81 
82     MPI_Win_allocate(sizeof(pair_struct_t) * DATA_SIZE, sizeof(pair_struct_t),
83                      MPI_INFO_NULL, MPI_COMM_WORLD, &tar_buf, &win);
84 
85     for (j = 0; j < LOOP * 6; j++) {
86 
87         MPI_Win_lock(MPI_LOCK_EXCLUSIVE, rank, 0, win);
88 
89         /* initialize data */
90         for (i = 0; i < DATA_SIZE; i++) {
91             tar_buf[i].a = (MTEST_PAIRTYPE_A) 0;
92             tar_buf[i].b = 0;
93             result_buf[i].a = (MTEST_PAIRTYPE_A) 0;
94             result_buf[i].b = 0;
95         }
96 
97         MPI_Win_unlock(rank, win);
98 
99         MPI_Barrier(MPI_COMM_WORLD);
100 
101         MPI_Win_fence(0, win);
102 
103         if (rank == 2) {
104             if (j < 2 * LOOP) {
105                 /* Work with FOP test (Test #1 to Test #2) */
106                 for (i = 0; i < OPS_NUM; i++) {
107 
108                     int curr_val = j * OPS_NUM + i;
109                     orig_buf[0].a = (MTEST_PAIRTYPE_A) (curr_val);
110                     orig_buf[0].b = curr_val;
111 
112                     MPI_Accumulate(orig_buf, 1, MTEST_MPI_PAIRTYPE,
113                                    0, 0, 1, MTEST_MPI_PAIRTYPE, MPI_REPLACE, win);
114                 }
115             } else {
116                 /* Work with GACC test (Test #3 to Test #6) */
117                 for (i = 0; i < OPS_NUM / GACC_SZ; i++) {
118 
119                     for (k = 0; k < GACC_SZ; k++) {
120                         int curr_val = j * OPS_NUM + i * GACC_SZ + k;
121                         orig_buf[k].a = (MTEST_PAIRTYPE_A) (curr_val);
122                         orig_buf[k].b = curr_val;
123                     }
124 
125                     MPI_Accumulate(orig_buf, GACC_SZ, MTEST_MPI_PAIRTYPE,
126                                    0, 0, GACC_SZ, MTEST_MPI_PAIRTYPE, MPI_REPLACE, win);
127                 }
128             }
129         } else if (rank == 1) {
130             /* equals to an atomic GET */
131             if (j < LOOP) {
132                 for (i = 0; i < DATA_SIZE; i++) {
133                     /* Test #1: FOP + MPI_NO_OP */
134                     MPI_Fetch_and_op(orig_buf, &(result_buf[i]), MTEST_MPI_PAIRTYPE,
135                                      0, 0, MPI_NO_OP, win);
136                 }
137             } else if (j < 2 * LOOP) {
138                 for (i = 0; i < DATA_SIZE; i++) {
139                     /* Test #2: FOP + MPI_NO_OP + NULL origin buffer address */
140                     MPI_Fetch_and_op(NULL, &(result_buf[i]), MTEST_MPI_PAIRTYPE,
141                                      0, 0, MPI_NO_OP, win);
142                 }
143             } else if (j < 3 * LOOP) {
144                 for (i = 0; i < DATA_SIZE / GACC_SZ; i++) {
145                     /* Test #3: GACC + MPI_NO_OP */
146                     MPI_Get_accumulate(orig_buf, GACC_SZ, MTEST_MPI_PAIRTYPE,
147                                        &(result_buf[i * GACC_SZ]), GACC_SZ, MTEST_MPI_PAIRTYPE,
148                                        0, 0, GACC_SZ, MTEST_MPI_PAIRTYPE, MPI_NO_OP, win);
149                 }
150             } else if (j < 4 * LOOP) {
151                 for (i = 0; i < DATA_SIZE / GACC_SZ; i++) {
152                     /* Test #4: GACC + MPI_NO_OP + NULL origin buffer address */
153                     MPI_Get_accumulate(NULL, GACC_SZ, MTEST_MPI_PAIRTYPE,
154                                        &(result_buf[i * GACC_SZ]), GACC_SZ, MTEST_MPI_PAIRTYPE,
155                                        0, 0, GACC_SZ, MTEST_MPI_PAIRTYPE, MPI_NO_OP, win);
156                 }
157             } else if (j < 5 * LOOP) {
158                 for (i = 0; i < DATA_SIZE / GACC_SZ; i++) {
159                     /* Test #5: GACC + MPI_NO_OP + zero origin count */
160                     MPI_Get_accumulate(orig_buf, 0, MTEST_MPI_PAIRTYPE,
161                                        &(result_buf[i * GACC_SZ]), GACC_SZ, MTEST_MPI_PAIRTYPE,
162                                        0, 0, GACC_SZ, MTEST_MPI_PAIRTYPE, MPI_NO_OP, win);
163                 }
164             } else if (j < 6 * LOOP) {
165                 for (i = 0; i < DATA_SIZE / GACC_SZ; i++) {
166                     /* Test #5: GACC + MPI_NO_OP + NULL origin datatype */
167                     MPI_Get_accumulate(orig_buf, GACC_SZ, MPI_DATATYPE_NULL,
168                                        &(result_buf[i * GACC_SZ]), GACC_SZ, MTEST_MPI_PAIRTYPE,
169                                        0, 0, GACC_SZ, MTEST_MPI_PAIRTYPE, MPI_NO_OP, win);
170                 }
171             }
172         }
173 
174         MPI_Win_fence(0, win);
175 
176         /* check results */
177         if (rank == 1) {
178             for (i = 0; i < DATA_SIZE; i++) {
179                 if (result_buf[i].a != (MTEST_PAIRTYPE_A) (result_buf[i].b)) {
180                     if (curr_errors < 10) {
181                         printf("LOOP %d: result_buf[%d].a = " MTEST_PAIRTYPE_A_STRFMT
182                                ", result_buf[%d].b = %d\n",
183                                j, i, result_buf[i].a, i, result_buf[i].b);
184                     }
185                     curr_errors++;
186                 }
187             }
188         }
189 
190         if (j % LOOP == 0) {
191             errs += curr_errors;
192             curr_errors = 0;
193         }
194     }
195 
196     MPI_Win_free(&win);
197 
198     MPI_Free_mem(orig_buf);
199     MPI_Free_mem(result_buf);
200 
201     MTest_Finalize(errs);
202 
203     return MTestReturnValue(errs);
204 }
205