71 #define zero_stripe ((struct Xt_offset_ext){ .start=0, .stride=0, .size=0 }) 75 int count, MPI_Datatype old_type);
78 MPI_Datatype old_type);
84 MPI_Comm_rank(comm, &rank);
86 char error_string[MPI_MAX_ERROR_STRING];
87 int length_of_error_string, error_class;
89 MPI_Error_class(error_code, &error_class);
90 MPI_Error_string(error_class, error_string, &length_of_error_string);
91 fprintf(stderr,
"%3d: %s\n", rank, error_string);
92 MPI_Error_string(error_code, error_string, &length_of_error_string);
93 fprintf(stderr,
"%3d: %s\n", rank, error_string);
94 MPI_Abort(comm, error_code);
98 static MPI_Datatype copy_mpi_datatype(MPI_Datatype old_type,
MPI_Comm comm) {
100 MPI_Datatype datatype;
102 xt_mpi_call(MPI_Type_dup(old_type, &datatype), comm);
108 gen_mpi_datatype_simple(
int displacement, MPI_Datatype old_type,
MPI_Comm comm)
110 MPI_Datatype datatype;
112 xt_mpi_call(MPI_Type_create_indexed_block(1, 1, &displacement, old_type,
120 gen_mpi_datatype_contiguous(
int displacement,
int blocklength,
121 MPI_Datatype old_type,
MPI_Comm comm) {
123 MPI_Datatype datatype;
125 if (displacement == 0)
126 xt_mpi_call(MPI_Type_contiguous(blocklength, old_type, &datatype),
129 xt_mpi_call(MPI_Type_create_indexed_block(1, blocklength,
130 &displacement, old_type,
140 gen_mpi_datatype_vector(
int count,
int blocklength,
int stride,
141 int offset, MPI_Datatype old_type,
MPI_Comm comm) {
143 MPI_Datatype datatype;
145 xt_mpi_call(MPI_Type_vector(count, blocklength, stride, old_type,
149 MPI_Datatype datatype_;
150 int hindexed_blocklength = 1;
151 MPI_Aint old_type_size, old_type_lb;
153 xt_mpi_call(MPI_Type_get_extent(old_type, &old_type_lb,
154 &old_type_size), comm);
156 MPI_Aint displacement = offset * old_type_size;
158 xt_mpi_call(MPI_Type_create_hindexed(1, &hindexed_blocklength,
159 &displacement, datatype, &datatype_),
162 datatype = datatype_;
170 gen_mpi_datatype_indexed_block(
int const * displacements,
int blocklength,
171 int count, MPI_Datatype old_type,
MPI_Comm comm)
173 MPI_Datatype datatype;
175 xt_mpi_call(MPI_Type_create_indexed_block(count, blocklength,
176 (
void *)displacements,
177 old_type, &datatype), comm);
184 gen_mpi_datatype_indexed(
const int *displacements,
const int *blocklengths,
185 int count, MPI_Datatype old_type,
MPI_Comm comm) {
187 MPI_Datatype datatype;
189 xt_mpi_call(MPI_Type_indexed(count, (
int*)blocklengths, (
void*)displacements,
190 old_type, &datatype), comm);
197 check_for_vector_type(
const int *displacements,
const int *blocklengths,
200 int blocklength = blocklengths[0];
202 for (
int i = 1; i < count; ++i)
203 if (blocklengths[i] != blocklength)
206 int stride = displacements[1] - displacements[0];
208 for (
int i = 1; i + 1 < count; ++i)
209 if (displacements[i+1] - displacements[i] != stride)
215 static inline int check_for_indexed_block_type(
const int *blocklengths,
218 int blocklength = blocklengths[0];
220 for (
int i = 1; i < count; ++i)
221 if (blocklengths[i] != blocklength)
230 const int *blocklengths,
231 int count, MPI_Datatype old_type,
237 MPI_Datatype datatype;
240 datatype = MPI_DATATYPE_NULL;
241 else if (count == 1 && blocklengths[0] == 1 && displacements[0] == 0)
242 datatype = copy_mpi_datatype(old_type, comm);
243 else if (count == 1 && blocklengths[0] == 1)
244 datatype = gen_mpi_datatype_simple(displacements[0], old_type, comm);
246 datatype = gen_mpi_datatype_contiguous(displacements[0], blocklengths[0],
248 else if (check_for_vector_type(displacements, blocklengths, count))
249 datatype = gen_mpi_datatype_vector(count, blocklengths[0],
250 displacements[1] - displacements[0],
251 displacements[0], old_type, comm);
252 else if (check_for_indexed_block_type(blocklengths, count))
253 datatype = gen_mpi_datatype_indexed_block(displacements, blocklengths[0],
254 count, old_type, comm);
256 datatype = gen_mpi_datatype_indexed(displacements, blocklengths, count,
264 MPI_Datatype old_type,
MPI_Comm comm) {
267 return MPI_DATATYPE_NULL;
273 int * blocklengths =
xmalloc((
size_t)count *
sizeof(*blocklengths));
279 while (i + j < count && displacements[i] + j == displacements[i + j])
281 blocklengths[new_count++] = j;
286 int * tmp_displ = NULL;
289 if (new_count != count) {
291 tmp_displ =
xmalloc((
size_t)new_count *
sizeof(*tmp_displ));
295 for (
int i = 0; i < new_count; ++i) {
297 tmp_displ[i] = displacements[offset];
298 offset += blocklengths[i];
303 displ = displacements;
305 MPI_Datatype datatype;
322 if (disp_len<1)
return 0;
326 while (p < disp_len) {
336 x.
stride = disp[p] - disp[p-1];
342 if (disp[p] - disp[p-1] == x.
stride) {
349 if (i >= vsize)
die(
"scan_stripe: vsize too small\n");
358 if (i >= vsize)
die(
"scan_stripe: vsize too small\n");
373 if (i >= vsize)
die(
"scan_stripe: vsize too small\n");
376 }
else if (x.
size == 2) {
377 if (i+1 >= vsize)
die(
"scan_stripe: vsize too small\n");
387 }
else if (x.
size == 1) {
388 if (i >= vsize)
die(
"scan_stripe: vsize too small\n");
399 for (
size_t j = 0; j < vn; j++) {
400 for (
int k = 0; k < v[j].size; ++k, ++p) {
401 int d = v[j].start + k*v[j].stride;
402 static const char die_msg[2][32] = {
"scan_stripe: internal error (1)",
403 "scan_stripe: internal error (2)" };
404 int err_code = p > disp_len || (disp[p] != d) * 2;
405 if (err_code)
die(die_msg[err_code - 1]);
408 if (p != disp_len)
die(
"scan_stripe: internal error (3)");
415 MPI_Datatype old_type,
int *disp, MPI_Datatype *dt) {
419 if (p >= vlen)
return 0;
420 int nstrides = v[p].
size;
422 if (nstrides < 2 || stride == 1 )
return 0;
426 *disp = vlen > 1 ? v[p].
start : 0;
429 xt_mpi_call(MPI_Type_vector(nstrides, 1, stride, old_type, &dt1),
437 MPI_Aint old_type_size, old_type_lb;
438 xt_mpi_call(MPI_Type_get_extent(old_type, &old_type_lb,
439 &old_type_size), Xt_default_comm);
441 MPI_Aint displacement = start * old_type_size;
444 xt_mpi_call(MPI_Type_create_hindexed(1, &bl2, &displacement, dt1, &dt2),
459 MPI_Datatype old_type,
int *disp, MPI_Datatype *dt) {
461 size_t p = *pstart_, pstart = p;
462 if (p+2 >= vlen || v[p].
stride != 1 || v[p+1].
stride != 1 )
return 0;
464 if (bl < 1 || v[p+1].
size != bl)
return 0;
469 while( p < vlen && v[p].
stride == 1 && v[p].
size == bl &&
473 size_t n = p - pstart;
474 if (n<3)
return false;
476 *disp = n == vlen ? 0 : v[pstart].
start;
479 xt_mpi_call(MPI_Type_vector((
int)n, bl, vstride, old_type, &dt1),
489 MPI_Aint old_type_size, old_type_lb;
490 xt_mpi_call(MPI_Type_get_extent(old_type, &old_type_lb,
491 &old_type_size), Xt_default_comm);
493 MPI_Aint displacement = start * old_type_size;
496 xt_mpi_call(MPI_Type_create_hindexed(1, &bl2, &displacement, dt1, &dt2),
506 MPI_Datatype old_type,
int *restrict disp, MPI_Datatype *dt) {
508 if (p >= vlen || v[p].
stride != 1 || v[p].
size < 2)
return 0;
510 int d = v[p].
start - (*disp = vlen > 1 ? v[p].
start : 0);
513 xt_mpi_call(MPI_Type_contiguous(v[p].
size, old_type, dt), Xt_default_comm) ;
515 xt_mpi_call(MPI_Type_create_indexed_block(1, v[p].size, &d, old_type, dt),
519 return v[p].
size != 0;
524 MPI_Datatype old_type,
int *disp, MPI_Datatype *dt) {
526 size_t p = *pstart_, pstart = p;
527 if (p >= vlen || v[p].
stride != 1 || v[p].
size < 2)
return 0;
531 while (p < vlen && v[p].
stride == 1);
533 size_t n = p - pstart;
535 if (n < 2)
return false;
537 int start = (*disp = n == vlen ? 0 : v[pstart].
start);
539 int *restrict bl =
xmalloc(2 * n *
sizeof (*bl)),
540 *restrict d = bl + n;
543 int bl0 = bl[0] = v[pstart].
size;
544 for (
size_t i = 1; i < n; i++) {
545 size_t iv = pstart + i;
548 hom_bl &= (bl[i] == bl0);
552 xt_mpi_call(MPI_Type_create_indexed_block((
int)n, bl0, d, old_type, dt),
555 xt_mpi_call(MPI_Type_indexed((
int)n, bl, d, old_type, dt), Xt_default_comm);
567 size_t vlen, MPI_Datatype old_type,
int *offset,
569 size_t ia = set_start;
571 if (ib <= ia || ib > vlen)
return 0;
574 for (
size_t i=ia; i < ib; i++)
580 if (ia == 0 && ib == vlen) {
590 int *restrict d =
xmalloc(
sizeof (*d) * (
size_t)n);
593 for (
size_t i=ia; i < ib; i++) {
594 size_t v_i_size = (size_t)(v[i].
size > 0 ? v[i].
size : 0);
595 for (
size_t k=0; k < v_i_size; k++) {
601 if (n==1 && d[0] == 0) {
608 xt_mpi_call(MPI_Type_dup(old_type, dt), Xt_default_comm);
610 xt_mpi_call(MPI_Type_create_indexed_block(n, 1, d, old_type, dt), Xt_default_comm);
621 size_t set_start = 0, set_end = 0;
622 MPI_Datatype *restrict wdt =
xmalloc(
sizeof(*wdt) * (
size_t)vlen);
623 int *restrict wdisp =
xmalloc(
sizeof (*wdisp) * (
size_t)vlen);
632 size_t mm = m + (set_start < set_end);
639 if (set_start < set_end) {
650 if (set_start < set_end) {
655 MPI_Datatype result_dt;
660 die(
"parse_stripe: internal error; wlen == 1 && match_disp != 0\n");
662 MPI_Aint old_type_lb, old_type_extent;
663 MPI_Aint *restrict wbdisp =
xmalloc((
size_t)wlen *
sizeof (*wbdisp));
664 int *restrict wblocklength
665 =
xmalloc((
size_t)wlen *
sizeof (*wblocklength));;
666 xt_mpi_call(MPI_Type_get_extent(old_type, &old_type_lb,
667 &old_type_extent), Xt_default_comm);
668 for(
size_t i=0; i<wlen; i++) {
669 wbdisp[i] = wdisp[i] * old_type_extent;
672 xt_mpi_call(MPI_Type_create_struct((
int)wlen, wblocklength, wbdisp,
673 wdt, &result_dt), Xt_default_comm);
676 for (
size_t i = 0; i < wlen; i++)
677 xt_mpi_call(MPI_Type_free(wdt+i), Xt_default_comm);
679 xt_mpi_call(MPI_Type_commit(&result_dt), Xt_default_comm);
687 int count, MPI_Datatype old_type,
690 if (count < 1)
return MPI_DATATYPE_NULL;
697 int count, MPI_Datatype old_type) {
699 if (count < 1)
return MPI_DATATYPE_NULL;
701 for (
size_t i=0; i<(size_t)count; ++i) {
702 v[i].start = disp[i];
704 v[i].size = blocklengths[i];
706 MPI_Datatype dt =
parse_stripe(v, (
size_t)count, old_type);
713 MPI_Datatype old_type) {
715 if (disp_len < 1)
return MPI_DATATYPE_NULL;
718 size_t vlen =
scan_stripe(disp, (
size_t)disp_len, v, (
size_t)disp_len);
743 void *attribute_val_out,
int *flag)
747 +
sizeof (used_map_elem));
754 *(
void **)attribute_val_out = new_comm_attr;
756 retval = MPI_SUCCESS;
759 retval = MPI_ERR_NO_MEM;
767 void *attribute_val,
void *
XT_UNUSED(extra_state))
779 &xt_mpi_comm_internal_keyval, NULL),
786 xt_mpi_tag_ub_val = *(
int *)attr;
791 xt_mpi_call(MPI_Comm_free_keyval(&xt_mpi_comm_internal_keyval),
800 xt_mpi_call(MPI_Comm_get_attr(comm, xt_mpi_comm_internal_keyval,
801 &attr_val, &attr_found),
803 return attr_found ? attr_val : NULL;
806 #if HAVE_DECL___BUILTIN_CTZL 807 #define ctzl(v) (__builtin_ctzl(v)) 808 #elif HAVE_DECL___BUILTIN_CLZL 810 ctzl(
unsigned long v) {
812 ulong_bits =
sizeof (
unsigned long) * CHAR_BIT,
816 int c = ulong_bits - __builtin_clzl(v) - 1;
823 ulong_bits =
sizeof (
unsigned long) * CHAR_BIT,
826 unsigned int c = ulong_bits;
827 v &= (
unsigned long)-(
long)v;
829 #if SIZEOF_UNSIGNED_LONG * CHAR_BIT == 64 830 if (v & UINT64_C(0x00000000ffffffff)) c -= 32;
831 if (v & UINT64_C(0x0000ffff0000ffff)) c -= 16;
832 if (v & UINT64_C(0x00ff00ff00ff00ff)) c -= 8;
833 if (v & UINT64_C(0x0f0f0f0f0f0f0f0f)) c -= 4;
834 if (v & UINT64_C(0x3333333333333333)) c -= 2;
835 if (v & UINT64_C(0x5555555555555555)) c -= 1;
836 #elif SIZEOF_UNSIGNED_LONG * CHAR_BIT == 32 837 if (v & 0x0000FFFFUL) c -= 16;
838 if (v & 0x00FF00FFUL) c -= 8;
839 if (v & 0x0F0F0F0FUL) c -= 4;
840 if (v & 0x33333333UL) c -= 2;
841 if (v & 0x55555555UL) c -= 1;
843 error
"Unexpected size of long.\n" 862 while (position < used_map_size
863 && comm_xt_attr_val->
used_map[position] == ~(used_map_elem)0)
865 if (position >= used_map_size) {
868 =
xmalloc(
sizeof (*new_comm_xt_attr_val)
869 + (used_map_size + 1) *
sizeof (used_map_elem));
871 new_comm_xt_attr_val->
used_map_size = (unsigned)(used_map_size + 1);
874 new_comm_xt_attr_val->
used_map[used_map_size] = 1U;
876 xt_mpi_call(MPI_Comm_set_attr(comm_dest, xt_mpi_comm_internal_keyval,
877 new_comm_xt_attr_val), comm_dest);
880 used_map_elem used_map_entry = comm_xt_attr_val->
used_map[position],
881 unset_lsb = ~used_map_entry & (used_map_entry + 1),
882 bit_pos = (used_map_elem)
ctzl(unset_lsb);
883 comm_xt_attr_val->
used_map[position] = used_map_entry | unset_lsb;
888 =
xmalloc(
sizeof (*comm_attr) +
sizeof (used_map_elem));
893 xt_mpi_call(MPI_Comm_set_attr(comm_dest, xt_mpi_comm_internal_keyval,
894 comm_attr), comm_dest);
920 =
xmalloc(
sizeof (*comm_attr) +
sizeof (used_map_elem));
924 xt_mpi_call(MPI_Comm_set_attr(comm, xt_mpi_comm_internal_keyval,
930 MPI_Request *restrict req,
931 int *restrict ops_completed,
MPI_Comm comm)
934 size_t num_req_ = (size_t)*num_req;
935 xt_mpi_call(MPI_Testsome(*num_req, req, &done_count, ops_completed,
936 MPI_STATUSES_IGNORE), comm);
937 if (done_count != MPI_UNDEFINED) {
938 if (num_req_ > (
size_t)done_count) {
941 i < (size_t)done_count && j >= num_req_ - (size_t)done_count;
943 if (ops_completed[i] < (
int)num_req_ - done_count) {
944 while (req[--j] == MPI_REQUEST_NULL);
945 req[ops_completed[i]] = req[j];
947 num_req_ -= (size_t)done_count;
952 *num_req = (int)num_req_;
953 return num_req_ == 0;
MPI_Datatype xt_mpi_generate_datatype(int const *displacements, int count, MPI_Datatype old_type, MPI_Comm comm)
void xt_mpi_comm_mark_exclusive(MPI_Comm comm)
static int gen_fallback_type(size_t set_start, size_t set_end, const struct Xt_offset_ext *v, size_t vlen, MPI_Datatype old_type, int *offset, MPI_Datatype *dt)
static bool match_block_vec(size_t *pstart_, const struct Xt_offset_ext *v, size_t vlen, MPI_Datatype old_type, int *disp, MPI_Datatype *dt)
base definitions header file
int xt_mpi_comm_internal_keyval
static bool match_indexed(size_t *pstart_, const struct Xt_offset_ext *v, size_t vlen, MPI_Datatype old_type, int *disp, MPI_Datatype *dt)
static int xt_mpi_comm_internal_keyval_delete(MPI_Comm XT_UNUSED(comm), int XT_UNUSED(comm_keyval), void *attribute_val, void *XT_UNUSED(extra_state))
static int xt_mpi_tag_ub_val
add versions of standard API functions not returning on error
bool xt_mpi_test_some(int *restrict num_req, MPI_Request *restrict req, int *restrict ops_completed, MPI_Comm comm)
unsigned long used_map_elem
void xt_mpi_error(int error_code, MPI_Comm comm)
MPI_Datatype xt_mpi_generate_datatype_block(const int *displacements, const int *blocklengths, int count, MPI_Datatype old_type, MPI_Comm comm)
static size_t scan_stripe(const int *disp, size_t disp_len, struct Xt_offset_ext *restrict v, size_t vsize)
MPI_Datatype xt_mpi_generate_datatype_stripe(const struct Xt_offset_ext *v, int count, MPI_Datatype old_type, MPI_Comm XT_UNUSED(comm))
static MPI_Datatype xt_mpi_generate_compact_datatype(int const *disp, int disp_len, MPI_Datatype old_type)
static int xt_mpi_comm_internal_keyval_copy(MPI_Comm XT_UNUSED(oldcomm), int XT_UNUSED(keyval), void *XT_UNUSED(extra_state), void *XT_UNUSED(attribute_val_in), void *attribute_val_out, int *flag)
static MPI_Datatype parse_stripe(const struct Xt_offset_ext *v, size_t vlen, MPI_Datatype old_type)
static int ctzl(unsigned long v)
void xt_mpi_finalize(void)
MPI_Comm xt_mpi_comm_smart_dup(MPI_Comm comm, int *tag_offset)
static MPI_Datatype xt_mpi_generate_compact_datatype_block(const int *disp, const int *blocklengths, int count, MPI_Datatype old_type)
void xt_mpi_comm_smart_dedup(MPI_Comm *comm, int tag_offset)
static int match_simple_vec(size_t *pstart_, const struct Xt_offset_ext *v, size_t vlen, MPI_Datatype old_type, int *disp, MPI_Datatype *dt)
#define xt_mpi_call(call, comm)
static bool match_contiguous(size_t *pstart_, const struct Xt_offset_ext *v, size_t vlen, MPI_Datatype old_type, int *restrict disp, MPI_Datatype *dt)
static struct xt_mpi_comm_internal_attr * xt_mpi_comm_get_internal_attr(MPI_Comm comm)