1 /**
2 * Copyright (C) Mellanox Technologies Ltd. 2001-2015. ALL RIGHTS RESERVED.
3 * Copyright (c) UT-Battelle, LLC. 2015. ALL RIGHTS RESERVED.
4 *
5 * See file LICENSE for terms.
6 */
7
8 #include "test_ucp_memheap.h"
9
10 #include <common/test_helpers.h>
11 #include <ucs/sys/sys.h>
12
13
14 std::vector<ucp_test_param>
enum_test_params(const ucp_params_t & ctx_params,const std::string & name,const std::string & test_case_name,const std::string & tls)15 test_ucp_memheap::enum_test_params(const ucp_params_t& ctx_params,
16 const std::string& name,
17 const std::string& test_case_name,
18 const std::string& tls)
19 {
20 std::vector<ucp_test_param> result;
21 generate_test_params_variant(ctx_params, name,
22 test_case_name, tls, 0, result);
23 generate_test_params_variant(ctx_params, name,
24 test_case_name + "/map_nb",
25 tls, UCP_MEM_MAP_NONBLOCK, result);
26 return result;
27 }
28
test_nonblocking_implicit_stream_xfer(nonblocking_send_func_t send,size_t size,int max_iter,size_t alignment,bool malloc_allocate,bool is_ep_flush)29 void test_ucp_memheap::test_nonblocking_implicit_stream_xfer(nonblocking_send_func_t send,
30 size_t size, int max_iter,
31 size_t alignment,
32 bool malloc_allocate,
33 bool is_ep_flush)
34 {
35 void *memheap;
36 size_t memheap_size;
37 ucp_mem_map_params_t params;
38 ucp_mem_attr_t mem_attr;
39 ucs_status_t status;
40
41 memheap = NULL;
42 memheap_size = max_iter * size + alignment;
43
44 if (max_iter == DEFAULT_ITERS) {
45 max_iter = 300 / ucs::test_time_multiplier();
46 }
47
48 if (size == DEFAULT_SIZE) {
49 size = ucs_max((size_t)ucs::rand() % (12 * UCS_KBYTE), alignment);
50 }
51 memheap_size = max_iter * size + alignment;
52
53 sender().connect(&receiver(), get_ep_params());
54
55 params.field_mask = UCP_MEM_MAP_PARAM_FIELD_ADDRESS |
56 UCP_MEM_MAP_PARAM_FIELD_LENGTH |
57 UCP_MEM_MAP_PARAM_FIELD_FLAGS;
58 params.length = memheap_size;
59 params.flags = GetParam().variant;
60 if (malloc_allocate) {
61 memheap = malloc(memheap_size);
62 params.address = memheap;
63 params.flags = params.flags & (~(UCP_MEM_MAP_ALLOCATE|UCP_MEM_MAP_FIXED));
64 } else if (params.flags & UCP_MEM_MAP_FIXED) {
65 params.address = ucs::mmap_fixed_address();
66 } else {
67 params.address = NULL;
68 params.flags |= UCP_MEM_MAP_ALLOCATE;
69 }
70
71 ucp_mem_h memh;
72 status = ucp_mem_map(receiver().ucph(), ¶ms, &memh);
73 ASSERT_UCS_OK(status);
74
75 mem_attr.field_mask = UCP_MEM_ATTR_FIELD_ADDRESS |
76 UCP_MEM_ATTR_FIELD_LENGTH;
77 status = ucp_mem_query(memh, &mem_attr);
78 ASSERT_UCS_OK(status);
79
80 EXPECT_GE(mem_attr.length, memheap_size);
81 if (!malloc_allocate) {
82 memheap = mem_attr.address;
83 }
84 memset(memheap, 0, memheap_size);
85
86 void *rkey_buffer;
87 size_t rkey_buffer_size;
88 status = ucp_rkey_pack(receiver().ucph(), memh, &rkey_buffer, &rkey_buffer_size);
89 ASSERT_UCS_OK(status);
90
91 ucp_rkey_h rkey;
92 status = ucp_ep_rkey_unpack(sender().ep(), rkey_buffer, &rkey);
93 ASSERT_UCS_OK(status);
94
95 std::string expected_data[300];
96 assert (max_iter <= 300);
97
98 for (int i = 0; i < max_iter; ++i) {
99 expected_data[i].resize(size);
100
101 ucs::fill_random(expected_data[i]);
102
103 ucs_assert(size * i + alignment <= memheap_size);
104
105 char *ptr = (char*)memheap + alignment + i * size;
106 (this->*send)(&sender(), size, (void*)ptr, rkey, expected_data[i]);
107
108 ASSERT_UCS_OK(status);
109
110 }
111
112 if (is_ep_flush) {
113 flush_ep(sender());
114 } else {
115 flush_worker(sender());
116 }
117
118 for (int i = 0; i < max_iter; ++i) {
119 char *ptr = (char*)memheap + alignment + i * size;
120 EXPECT_EQ(expected_data[i].substr(0, 20),
121 std::string(ptr, expected_data[i].length()).substr(0, 20)) <<
122 ((void*)ptr);
123 }
124
125 ucp_rkey_destroy(rkey);
126
127 disconnect(sender());
128
129 ucp_rkey_buffer_release(rkey_buffer);
130 status = ucp_mem_unmap(receiver().ucph(), memh);
131 ASSERT_UCS_OK(status);
132
133 if (malloc_allocate) {
134 free(memheap);
135 }
136 }
137
138 /* NOTE: alignment is ignored if memheap_size is not default */
test_blocking_xfer(blocking_send_func_t send,size_t memheap_size,int max_iter,size_t alignment,bool malloc_allocate,bool is_ep_flush)139 void test_ucp_memheap::test_blocking_xfer(blocking_send_func_t send,
140 size_t memheap_size, int max_iter,
141 size_t alignment,
142 bool malloc_allocate,
143 bool is_ep_flush)
144 {
145 ucp_mem_map_params_t params;
146 ucp_mem_attr_t mem_attr;
147 ucs_status_t status;
148 size_t size;
149 int zero_offset = 0;
150
151 if (max_iter == DEFAULT_ITERS) {
152 max_iter = 300 / ucs::test_time_multiplier();
153 }
154
155 if (memheap_size == DEFAULT_SIZE) {
156 memheap_size = 3 * UCS_KBYTE;
157 zero_offset = 1;
158 }
159
160 sender().connect(&receiver(), get_ep_params());
161
162 /* avoid deadlock for blocking rma/amo */
163 flush_worker(sender());
164
165 ucp_mem_h memh;
166 void *memheap = NULL;
167
168 params.field_mask = UCP_MEM_MAP_PARAM_FIELD_ADDRESS |
169 UCP_MEM_MAP_PARAM_FIELD_LENGTH |
170 UCP_MEM_MAP_PARAM_FIELD_FLAGS;
171 params.length = memheap_size;
172 params.flags = GetParam().variant;
173 if (malloc_allocate) {
174 memheap = malloc(memheap_size);
175 params.address = memheap;
176 params.flags = params.flags & (~(UCP_MEM_MAP_ALLOCATE|UCP_MEM_MAP_FIXED));
177 } else if (params.flags & UCP_MEM_MAP_FIXED) {
178 params.address = ucs::mmap_fixed_address();
179 params.flags |= UCP_MEM_MAP_ALLOCATE;
180 } else {
181 params.address = NULL;
182 params.flags |= UCP_MEM_MAP_ALLOCATE;
183 }
184
185 status = ucp_mem_map(receiver().ucph(), ¶ms, &memh);
186 ASSERT_UCS_OK(status);
187
188 mem_attr.field_mask = UCP_MEM_ATTR_FIELD_ADDRESS |
189 UCP_MEM_ATTR_FIELD_LENGTH;
190 status = ucp_mem_query(memh, &mem_attr);
191 ASSERT_UCS_OK(status);
192 EXPECT_GE(mem_attr.length, memheap_size);
193 if (!memheap) {
194 memheap = mem_attr.address;
195 }
196 memset(memheap, 0, memheap_size);
197
198 void *rkey_buffer;
199 size_t rkey_buffer_size;
200 status = ucp_rkey_pack(receiver().ucph(), memh, &rkey_buffer, &rkey_buffer_size);
201 ASSERT_UCS_OK(status);
202
203 ucp_rkey_h rkey;
204 status = ucp_ep_rkey_unpack(sender().ep(), rkey_buffer, &rkey);
205 ASSERT_UCS_OK(status);
206
207 ucp_rkey_buffer_release(rkey_buffer);
208
209 for (int i = 0; i < max_iter; ++i) {
210 size_t offset;
211
212 if (!zero_offset) {
213 size = ucs_max(ucs::rand() % (memheap_size - alignment - 1), alignment);
214 offset = ucs::rand() % (memheap_size - size - alignment);
215 } else {
216 size = memheap_size;
217 offset = 0;
218 }
219
220 offset = ucs_align_up(offset, alignment);
221
222 ucs_assert(((((uintptr_t)memheap + offset)) % alignment) == 0);
223 ucs_assert(size + offset <= memheap_size);
224
225 std::string expected_data;
226 expected_data.resize(size);
227
228 ucs::fill_random(expected_data);
229 (this->*send)(&sender(), size, (void*)((uintptr_t)memheap + offset),
230 rkey, expected_data);
231
232 if (is_ep_flush) {
233 flush_ep(sender());
234 } else {
235 flush_worker(sender());
236 }
237
238 EXPECT_EQ(expected_data,
239 std::string((char*)memheap + offset, expected_data.length()));
240
241 expected_data.clear();
242 }
243
244 ucp_rkey_destroy(rkey);
245
246 disconnect(sender());
247
248 status = ucp_mem_unmap(receiver().ucph(), memh);
249 ASSERT_UCS_OK(status);
250
251 if (malloc_allocate) {
252 free(memheap);
253 }
254 }
255