Skip to content

Commit ddd923c

Browse files
committed
TEST/MPI: fix global memh and mem-map test lifecycle
1 parent 4780501 commit ddd923c

2 files changed

Lines changed: 98 additions & 42 deletions

File tree

test/mpi/test_case.cc

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -230,30 +230,40 @@ ucc_status_t TestCase::register_memh_global(void *buf, size_t size,
230230

231231
ucc_status_t TestCase::register_memhs(void *sbuf, size_t ssize, void *dbuf, size_t dsize)
232232
{
233+
int all_have_dbuf, has_dbuf;
234+
233235
if (memh_mode == UCC_TEST_MEMH_NONE) {
234236
return UCC_OK;
235237
}
236238

237239
if (memh_mode == UCC_TEST_MEMH_GLOBAL) {
238-
if (sbuf && ssize > 0) {
239-
UCC_CHECK(register_memh_global(sbuf, ssize, &src_memh,
240-
&src_global_memh));
241-
args.src_memh.global_memh = src_global_memh;
242-
args.mask |= UCC_COLL_ARGS_FIELD_MEM_MAP_SRC_MEMH;
243-
args.flags |= UCC_COLL_ARGS_FLAG_SRC_MEMH_GLOBAL;
244-
}
245-
if (dbuf && dsize > 0) {
246-
UCC_CHECK(register_memh_global(dbuf, dsize, &dst_memh,
247-
&dst_global_memh));
248-
args.dst_memh.global_memh = dst_global_memh;
249-
args.mask |= UCC_COLL_ARGS_FIELD_MEM_MAP_DST_MEMH;
250-
args.flags |= UCC_COLL_ARGS_FLAG_DST_MEMH_GLOBAL;
240+
/* Global destination handles are consumed by alltoall/alltoallv
241+
* algorithms, including TL/CUDA push and TL/UCP one-sided paths.
242+
* Other collective types have consumers that treat a present memh
243+
* field as a local handle and must not be given an array.
244+
*/
245+
if (args.coll_type != UCC_COLL_TYPE_ALLTOALL &&
246+
args.coll_type != UCC_COLL_TYPE_ALLTOALLV) {
247+
return UCC_OK;
251248
}
252-
/* Flags are only honored when FIELD_FLAGS is present in the mask. */
253-
if (args.flags & (UCC_COLL_ARGS_FLAG_SRC_MEMH_GLOBAL |
254-
UCC_COLL_ARGS_FLAG_DST_MEMH_GLOBAL)) {
255-
args.mask |= UCC_COLL_ARGS_FIELD_FLAGS;
249+
250+
/* register_memh_global contains MPI collectives. Enter it only when
251+
* every rank has a destination buffer so all ranks execute the same
252+
* exchange sequence (including zero-count alltoallv cases).
253+
*/
254+
has_dbuf = dbuf && dsize > 0;
255+
MPI_Allreduce(&has_dbuf, &all_have_dbuf, 1, MPI_INT, MPI_MIN,
256+
team.comm);
257+
if (!all_have_dbuf) {
258+
return UCC_OK;
256259
}
260+
261+
UCC_CHECK(register_memh_global(dbuf, dsize, &dst_memh,
262+
&dst_global_memh));
263+
args.dst_memh.global_memh = dst_global_memh;
264+
args.mask |= UCC_COLL_ARGS_FIELD_FLAGS |
265+
UCC_COLL_ARGS_FIELD_MEM_MAP_DST_MEMH;
266+
args.flags |= UCC_COLL_ARGS_FLAG_DST_MEMH_GLOBAL;
257267
return UCC_OK;
258268
}
259269

@@ -305,6 +315,7 @@ TestCase::TestCase(ucc_test_team_t &_team, ucc_coll_type_t ct,
305315
src_global_memh = NULL;
306316
dst_global_memh = NULL;
307317
memh_global_size = 0;
318+
req = NULL;
308319
test_skip = TEST_SKIP_NONE;
309320
args.flags = 0;
310321
args.mask = 0;
@@ -331,7 +342,7 @@ TestCase::~TestCase()
331342
MPI_Cancel(&progress_request);
332343
MPI_Wait(&progress_request, &status);
333344

334-
if (TEST_SKIP_NONE == test_skip) {
345+
if (TEST_SKIP_NONE == test_skip && req) {
335346
UCC_CHECK(ucc_collective_finalize(req));
336347
}
337348

test/mpi/test_mem_map.cc

Lines changed: 69 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#include "test_mpi.h"
88
#include "mpi_util.h"
9+
#include <climits>
910
#include <cstring>
1011
#include <vector>
1112
#include "components/mc/ucc_mc.h"
@@ -85,24 +86,73 @@ class TestMemMap : public TestCase
8586
void run(bool triggered) override
8687
{
8788
(void)triggered; /* mem_map tests don't support triggered mode */
88-
ucc_mem_map_params_t map_params;
89-
ucc_mem_map_t segment;
90-
int rank;
89+
ucc_mem_map_mem_h export_memh = nullptr;
90+
ucc_mem_map_params_t map_params = {};
91+
ucc_mem_map_t segment = {};
92+
size_t export_size = 0;
93+
uint64_t recv_size = 0;
94+
int comm_size, peer, rank;
95+
ucc_status_t status;
9196

9297
MPI_Comm_rank(team.comm, &rank);
98+
MPI_Comm_size(team.comm, &comm_size);
9399

94100
/* Set up memory map parameters */
95101
segment.address = test_buffer;
96102
segment.len = buffer_size;
97103
map_params.segments = &segment;
98104
map_params.n_segments = 1;
99105

106+
if (!is_export_test) {
107+
/* Import operates on an exchanged serialized export handle. Send
108+
* each rank's blob to its next peer so import never receives a
109+
* NULL or otherwise uninitialized handle.
110+
*/
111+
status = ucc_mem_map(team.ctx, UCC_MEM_MAP_MODE_EXPORT,
112+
&map_params, &export_size, &export_memh);
113+
if (status != UCC_OK) {
114+
if (status == UCC_ERR_NOT_SUPPORTED ||
115+
status == UCC_ERR_NOT_IMPLEMENTED) {
116+
test_skip = TEST_SKIP_NOT_SUPPORTED;
117+
return;
118+
}
119+
UCC_CHECK(status);
120+
}
121+
if (!export_memh || export_size == 0) {
122+
UCC_CHECK(UCC_ERR_INVALID_PARAM);
123+
}
124+
125+
peer = (rank + 1) % comm_size;
126+
uint64_t send_size = export_size;
127+
MPI_Sendrecv(&send_size, 1, MPI_UINT64_T, peer, 1001,
128+
&recv_size, 1, MPI_UINT64_T,
129+
(rank + comm_size - 1) % comm_size, 1001,
130+
team.comm, MPI_STATUS_IGNORE);
131+
132+
if (send_size > INT_MAX || recv_size > INT_MAX) {
133+
UCC_CHECK(UCC_ERR_INVALID_PARAM);
134+
}
135+
memh = ucc_malloc(recv_size, "import memh blob");
136+
UCC_MALLOC_CHECK(memh);
137+
MPI_Sendrecv(export_memh, static_cast<int>(send_size), MPI_BYTE,
138+
peer, 1002, memh, static_cast<int>(recv_size), MPI_BYTE,
139+
(rank + comm_size - 1) % comm_size, 1002,
140+
team.comm, MPI_STATUS_IGNORE);
141+
memh_size = recv_size;
142+
}
143+
100144
/* Test memory map */
101-
ucc_status_t status = ucc_mem_map(team.ctx, mode, &map_params,
102-
&memh_size, &memh);
145+
status = ucc_mem_map(team.ctx, mode, &map_params, &memh_size, &memh);
103146
if (status != UCC_OK) {
147+
if (export_memh) {
148+
UCC_CHECK(ucc_mem_unmap(&export_memh));
149+
}
104150
if (status == UCC_ERR_NOT_SUPPORTED ||
105151
status == UCC_ERR_NOT_IMPLEMENTED) {
152+
if (memh) {
153+
ucc_free(memh);
154+
memh = nullptr;
155+
}
106156
test_skip = TEST_SKIP_NOT_SUPPORTED;
107157
return;
108158
}
@@ -112,19 +162,22 @@ class TestMemMap : public TestCase
112162
if (!memh) {
113163
std::cerr << "Rank " << rank << ": Memory handle is NULL"
114164
<< std::endl;
115-
return;
165+
UCC_CHECK(UCC_ERR_INVALID_PARAM);
116166
}
117-
if (memh_size == 0) {
167+
if (is_export_test && memh_size == 0) {
118168
std::cerr << "Rank " << rank << ": Memory handle size is 0"
119169
<< std::endl;
120-
return;
170+
UCC_CHECK(UCC_ERR_INVALID_PARAM);
121171
}
122172

123173
/* Verify data integrity after mapping */
124174
UCC_CHECK(check());
125175

126176
/* Test unmap */
127177
UCC_CHECK(ucc_mem_unmap(&memh));
178+
if (export_memh) {
179+
UCC_CHECK(ucc_mem_unmap(&export_memh));
180+
}
128181
if (memh != nullptr) {
129182
std::cerr << "Rank " << rank
130183
<< ": Memory handle not NULL after unmap" << std::endl;
@@ -205,9 +258,6 @@ class TestMemMapStress : public TestCase
205258
ucc_mem_unmap(&memh);
206259
}
207260
}
208-
if (test_buffer) {
209-
ucc_free(test_buffer);
210-
}
211261
}
212262

213263
ucc_status_t set_input(int iter_persistent = 0) override
@@ -260,8 +310,8 @@ class TestMemMapStress : public TestCase
260310
ucc_mem_map_mem_h memh;
261311
size_t memh_size;
262312

263-
/* Fill buffer with iteration-specific pattern */
264-
memset(test_buffer, 0xCC + rank + i, buffer_size);
313+
/* Keep the contents stable while repeatedly mapping the buffer. */
314+
memset(test_buffer, 0xBB + rank, buffer_size);
265315

266316
ucc_status_t status = ucc_mem_map(team.ctx, UCC_MEM_MAP_MODE_EXPORT,
267317
&map_params, &memh_size, &memh);
@@ -528,26 +578,21 @@ void run_mem_map_tests(UccTestMpi *test,
528578
if (!tc) continue;
529579

530580
if (TEST_SKIP_NONE == tc->test_skip) {
581+
UCC_CHECK(tc->set_input());
531582
tc->run(false);
532583
} else {
533584
results.push_back(
534585
std::make_tuple(tc->args.coll_type, UCC_ERR_LAST));
535586
continue;
536587
}
537588

538-
ucc_status_t status;
539-
do {
540-
tc->mpi_progress();
541-
status = tc->test();
542-
} while (status == UCC_INPROGRESS);
543-
544-
if (UCC_OK != status) {
545-
std::cerr << "error during mem_map test: "
546-
<< ucc_status_string(status) << std::endl;
547-
MPI_Abort(MPI_COMM_WORLD, -1);
589+
if (TEST_SKIP_NONE != tc->test_skip) {
590+
results.push_back(
591+
std::make_tuple(tc->args.coll_type, UCC_ERR_LAST));
592+
continue;
548593
}
549594

550-
status = tc->check();
595+
ucc_status_t status = tc->check();
551596
results.push_back(
552597
std::make_tuple(tc->args.coll_type, status));
553598
}

0 commit comments

Comments
 (0)