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