This source file includes following definitions.
- ompi_osc_base_get_primitive_type_info
- ompi_osc_base_process_op
- ompi_osc_base_sndrcv_op
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 #include "ompi_config.h"
31
32 #include "opal/datatype/opal_convertor.h"
33 #include "opal/datatype/opal_convertor_internal.h"
34 #include "opal/datatype/opal_datatype_prototypes.h"
35 #include "opal/util/show_help.h"
36
37 #include "ompi/op/op.h"
38 #include "ompi/datatype/ompi_datatype.h"
39 #include "ompi/datatype/ompi_datatype_internal.h"
40
41 #include "osc_base_obj_convert.h"
42 #include "ompi/memchecker.h"
43
44 #define OMPI_OSC_BASE_DECODE_MAX 32
45
46 int
47 ompi_osc_base_get_primitive_type_info(ompi_datatype_t *datatype,
48 ompi_datatype_t **prim_datatype,
49 uint32_t *prim_count)
50 {
51 ompi_datatype_t *primitive_datatype = NULL;
52 size_t datatype_size, primitive_size, primitive_count;
53
54 primitive_datatype = ompi_datatype_get_single_predefined_type_from_args(datatype);
55 if( NULL == primitive_datatype ) {
56 *prim_count = 0;
57 return OMPI_SUCCESS;
58 }
59 ompi_datatype_type_size( datatype, &datatype_size );
60 ompi_datatype_type_size( primitive_datatype, &primitive_size );
61 primitive_count = datatype_size / primitive_size;
62 #if OPAL_ENABLE_DEBUG
63 assert( 0 == (datatype_size % primitive_size) );
64 #endif
65
66
67 *prim_datatype = primitive_datatype;
68 *prim_count = (uint32_t)primitive_count;
69
70 return OMPI_SUCCESS;
71 }
72
73 int ompi_osc_base_process_op (void *outbuf, void *inbuf, size_t inbuflen,
74 struct ompi_datatype_t *datatype, int count,
75 ompi_op_t *op)
76 {
77 if (op == &ompi_mpi_op_replace.op) {
78 return OMPI_ERR_NOT_SUPPORTED;
79 }
80
81
82 if(MPI_MINLOC == op || MPI_MAXLOC == op) {
83 if(MPI_SHORT_INT == datatype ||
84 MPI_DOUBLE_INT == datatype ||
85 MPI_LONG_INT == datatype ||
86 MPI_LONG_DOUBLE_INT == datatype) {
87 ompi_communicator_t *comm = &ompi_mpi_comm_world.comm;
88 opal_output(0, "Error: %s datatype is currently "
89 "unsupported for MPI_MINLOC/MPI_MAXLOC "
90 "operation\n", datatype->name);
91 opal_show_help("help-mpi-api.txt", "mpi-abort", true,
92 comm->c_my_rank,
93 ('\0' != comm->c_name[0]) ? comm->c_name : "<Unknown>",
94 -1);
95
96 ompi_mpi_abort(comm, -1);
97 }
98 }
99
100 if (ompi_datatype_is_predefined(datatype)) {
101 ompi_op_reduce(op, inbuf, outbuf, count, datatype);
102 } else {
103 opal_convertor_t convertor;
104 struct ompi_datatype_t *primitive_datatype = NULL;
105 struct iovec iov[OMPI_OSC_BASE_DECODE_MAX];
106 uint32_t iov_count;
107 size_t size, primitive_size;
108 ptrdiff_t lb, extent;
109 bool done;
110
111 primitive_datatype = ompi_datatype_get_single_predefined_type_from_args(datatype);
112 ompi_datatype_type_size (primitive_datatype, &primitive_size);
113
114 if (ompi_datatype_is_contiguous_memory_layout (datatype, count) &&
115 1 == datatype->super.desc.used) {
116
117
118
119 (void)ompi_datatype_type_size(datatype, &size);
120 count *= (size / primitive_size);
121 assert( 0 == (size % primitive_size) );
122
123
124
125 ompi_datatype_get_extent (datatype, &lb, &extent);
126 outbuf = (void *)((uintptr_t) outbuf + lb);
127
128 ompi_op_reduce(op, inbuf, outbuf, count, primitive_datatype);
129 return OMPI_SUCCESS;
130 }
131
132
133 OBJ_CONSTRUCT(&convertor, opal_convertor_t);
134 opal_convertor_copy_and_prepare_for_recv(ompi_mpi_local_convertor, &datatype->super,
135 count, outbuf, 0, &convertor);
136
137 do {
138 iov_count = OMPI_OSC_BASE_DECODE_MAX;
139 done = opal_convertor_raw (&convertor, iov, &iov_count, &size);
140
141 for (uint32_t i = 0 ; i < iov_count ; ++i) {
142 int primitive_count = iov[i].iov_len / primitive_size;
143 ompi_op_reduce (op, inbuf, iov[i].iov_base, primitive_count, primitive_datatype);
144 inbuf = (void *)((intptr_t) inbuf + iov[i].iov_len);
145 }
146 } while (!done);
147
148 MEMCHECKER(
149 memchecker_convertor_call(&opal_memchecker_base_mem_noaccess,
150 &convertor);
151 );
152
153 opal_convertor_cleanup (&convertor);
154 OBJ_DESTRUCT(&convertor);
155 }
156
157 return OMPI_SUCCESS;
158 }
159
160 int ompi_osc_base_sndrcv_op (const void *origin, int32_t origin_count,
161 struct ompi_datatype_t *origin_dt,
162 void *target, int32_t target_count,
163 struct ompi_datatype_t *target_dt,
164 ompi_op_t *op)
165 {
166 ompi_datatype_t *origin_primitive, *target_primitive;
167 opal_convertor_t origin_convertor, target_convertor;
168 struct iovec origin_iovec[OMPI_OSC_BASE_DECODE_MAX];
169 struct iovec target_iovec[OMPI_OSC_BASE_DECODE_MAX];
170 uint32_t origin_iov_count, target_iov_count;
171 uint32_t origin_iov_index, target_iov_index;
172 size_t origin_size, target_size, primitive_size;
173 int primitive_count;
174 size_t acc_len;
175 bool done;
176
177 if (ompi_datatype_is_predefined(origin_dt) && origin_dt == target_dt) {
178 ompi_op_reduce(op, (void *)origin, target, origin_count, origin_dt);
179
180 return OMPI_SUCCESS;
181 }
182
183 origin_primitive = ompi_datatype_get_single_predefined_type_from_args(origin_dt);
184 target_primitive = ompi_datatype_get_single_predefined_type_from_args(target_dt);
185
186
187 if (OPAL_UNLIKELY(origin_primitive != target_primitive)) {
188 return OMPI_ERR_RMA_SYNC;
189 }
190
191 ompi_datatype_type_size (target_primitive, &primitive_size);
192
193 OBJ_CONSTRUCT(&origin_convertor, opal_convertor_t);
194 opal_convertor_copy_and_prepare_for_send (ompi_mpi_local_convertor, &origin_dt->super,
195 origin_count, origin, 0, &origin_convertor);
196
197 OBJ_CONSTRUCT(&target_convertor, opal_convertor_t);
198 opal_convertor_copy_and_prepare_for_recv (ompi_mpi_local_convertor, &target_dt->super,
199 target_count, target, 0, &target_convertor);
200
201 target_iov_index = 0;
202 target_iov_count = 0;
203
204 do {
205
206 origin_iov_count = OMPI_OSC_BASE_DECODE_MAX;
207 origin_iov_index = 0;
208
209 done = opal_convertor_raw (&origin_convertor, origin_iovec, &origin_iov_count, &origin_size);
210
211
212 while (origin_iov_index != origin_iov_count) {
213 if (target_iov_index == target_iov_count) {
214
215 target_iov_count = OMPI_OSC_BASE_DECODE_MAX;
216 target_iov_index = 0;
217 (void) opal_convertor_raw (&target_convertor, target_iovec, &target_iov_count, &target_size);
218 }
219
220
221 assert (0 != target_iov_count);
222
223
224 if (target_iovec[target_iov_index].iov_len < origin_iovec[origin_iov_index].iov_len) {
225 acc_len = target_iovec[target_iov_index].iov_len;
226 } else {
227 acc_len = origin_iovec[origin_iov_index].iov_len;
228 }
229
230 primitive_count = acc_len / primitive_size;
231
232 ompi_op_reduce (op, origin_iovec[origin_iov_index].iov_base, target_iovec[target_iov_index].iov_base,
233 primitive_count, target_primitive);
234
235
236 target_iovec[target_iov_index].iov_len -= acc_len;
237 origin_iovec[origin_iov_index].iov_len -= acc_len;
238 target_iovec[target_iov_index].iov_base = (void *)((intptr_t) target_iovec[target_iov_index].iov_base + acc_len);
239 origin_iovec[origin_iov_index].iov_base = (void *)((intptr_t) origin_iovec[origin_iov_index].iov_base + acc_len);
240
241 origin_iov_index += 0 == origin_iovec[origin_iov_index].iov_len;
242 target_iov_index += 0 == target_iovec[target_iov_index].iov_len;
243 }
244 } while (!done);
245
246 opal_convertor_cleanup (&origin_convertor);
247 OBJ_DESTRUCT(&origin_convertor);
248
249 opal_convertor_cleanup (&target_convertor);
250 OBJ_DESTRUCT(&target_convertor);
251
252 return OMPI_SUCCESS;
253 }