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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284
|
/**
* Copyright (C) Mellanox Technologies Ltd. 2001-2015. ALL RIGHTS RESERVED.
* Copyright (c) UT-Battelle, LLC. 2015. ALL RIGHTS RESERVED.
*
* See file LICENSE for terms.
*/
#include "test_ucp_memheap.h"
#include <ucs/sys/sys.h>
extern "C" {
#include <ucp/core/ucp_mm.h> /* for UCP_MEM_IS_ACCESSIBLE_FROM_CPU */
}
class test_ucp_rma : public test_ucp_memheap {
public:
using iov_op_t = ucs_status_ptr_t (test_ucp_rma::*)(
size_t size, void *target_ptr, ucp_rkey_h rkey, void *expected_data,
ucp_request_param_t *param, ucp_dt_iov_t *iov, size_t iov_count,
void *arg);
static void get_test_variants(std::vector<ucp_test_variant>& variants) {
add_variant_with_value(variants, UCP_FEATURE_RMA, 0, "flush_worker");
add_variant_with_value(variants, UCP_FEATURE_RMA, FLUSH_EP, "flush_ep");
add_variant_with_value(variants, UCP_FEATURE_RMA,
FLUSH_EP | ENABLE_PROTO, "flush_ep_proto");
}
virtual void init() {
if (enable_proto()) {
modify_config("PROTO_ENABLE", "y");
}
test_ucp_memheap::init();
}
void do_nbi_iov(iov_op_t op, size_t size, void *target_ptr, ucp_rkey_h rkey,
void *expected_data, void *arg) {
ucp_dt_iov_t iov[UCP_MAX_IOV];
ucs_status_ptr_t status_ptr;
ucp_request_param_t param;
param.op_attr_mask = UCP_OP_ATTR_FIELD_DATATYPE;
param.datatype = DATATYPE_IOV;
for (auto iov_count = 0; iov_count <= UCP_MAX_IOV;
iov_count += ucs_max(iov_count, 1)) {
status_ptr = (this->*op)(size, target_ptr, rkey, expected_data,
¶m, iov, iov_count, arg);
flush_ep(sender());
request_release(status_ptr);
}
}
void put_b(size_t size, void *target_ptr, ucp_rkey_h rkey,
void *expected_data, void *arg) {
ucs_status_ptr_t status_ptr = do_put(size, target_ptr, rkey,
expected_data, arg);
request_wait(status_ptr);
}
void put_nbi(size_t size, void *target_ptr, ucp_rkey_h rkey,
void *expected_data, void *arg) {
ucs_status_ptr_t status_ptr = do_put(size, target_ptr, rkey,
expected_data, arg);
request_release(status_ptr);
}
void put_nbi_iov(size_t size, void *target_ptr, ucp_rkey_h rkey,
void *expected_data, void *arg) {
do_nbi_iov(&test_ucp_rma::do_put_iov, size, target_ptr, rkey,
expected_data, arg);
}
void get_b(size_t size, void *target_ptr, ucp_rkey_h rkey,
void *expected_data, void *arg) {
ucs_status_ptr_t status_ptr = do_get(size, target_ptr, rkey,
expected_data);
request_wait(status_ptr);
}
void get_nbi(size_t size, void *target_ptr, ucp_rkey_h rkey,
void *expected_data, void *arg) {
ucs_status_ptr_t status_ptr = do_get(size, target_ptr, rkey,
expected_data);
request_release(status_ptr);
}
void get_nbi_iov(size_t size, void *target_ptr, ucp_rkey_h rkey,
void *expected_data, void *arg) {
do_nbi_iov(&test_ucp_rma::do_get_iov, size, target_ptr, rkey,
expected_data, arg);
}
protected:
static size_t default_max_size() {
return (100 * UCS_MBYTE) / ucs::test_time_multiplier();
}
void test_mem_types(send_func_t send_func, size_t min_size = 128,
size_t max_size = default_max_size()) {
const std::vector<std::vector<ucs_memory_type_t> >& pairs =
ucs::supported_mem_type_pairs();
for (size_t i = 0; i < pairs.size(); ++i) {
/* Memory type put/get is fully supported only with new protocols */
if (!enable_proto() &&
(!UCP_MEM_IS_HOST(pairs[i][0]) ||
!UCP_MEM_IS_HOST(pairs[i][1]))) {
continue;
}
test_message_sizes(send_func, min_size, max_size, pairs[i][0],
pairs[i][1], 0);
}
/* test non-blocking map with host memory */
test_message_sizes(send_func, min_size, max_size, UCS_MEMORY_TYPE_HOST,
UCS_MEMORY_TYPE_HOST, UCP_MEM_MAP_NONBLOCK);
}
bool enable_proto() {
return get_variant_value() & ENABLE_PROTO;
}
private:
/* Test variants */
enum {
FLUSH_EP = UCS_BIT(0), /* If not set, flush worker */
ENABLE_PROTO = UCS_BIT(1)
};
void init_iov(size_t size, ucp_dt_iov_t *iov, size_t iov_count,
void *expected_data) {
const auto iov_buffer_length = size / iov_count;
for (size_t i = 0; i < iov_count; ++i) {
iov[i].buffer = UCS_PTR_BYTE_OFFSET(expected_data,
i * iov_buffer_length);
iov[i].length = iov_buffer_length;
}
iov[iov_count - 1].length += size % iov_count;
}
ucs_status_ptr_t do_put(size_t size, void *target_ptr, ucp_rkey_h rkey,
void *expected_data, void *arg) {
ucs_memory_type_t *mem_types = reinterpret_cast<ucs_memory_type_t*>(arg);
mem_buffer::pattern_fill(expected_data, size, ucs::rand(), mem_types[0]);
ucp_request_param_t param;
param.op_attr_mask = 0;
return ucp_put_nbx(sender().ep(), expected_data, size,
(uintptr_t)target_ptr, rkey, ¶m);
}
ucs_status_ptr_t do_put_iov(size_t size, void *target_ptr, ucp_rkey_h rkey,
void *expected_data, ucp_request_param_t *param,
ucp_dt_iov_t *iov, size_t iov_count, void *arg) {
ucs_memory_type_t *mem_types;
if (iov_count > 0) {
mem_types = reinterpret_cast<ucs_memory_type_t*>(arg);
mem_buffer::pattern_fill(expected_data, size, ucs::rand(),
mem_types[0]);
init_iov(size, iov, iov_count, expected_data);
}
return ucp_put_nbx(sender().ep(), iov, iov_count, (uintptr_t)target_ptr,
rkey, param);
}
ucs_status_ptr_t do_get(size_t size, void *target_ptr, ucp_rkey_h rkey,
void *expected_data) {
ucp_request_param_t param;
param.op_attr_mask = 0;
return ucp_get_nbx(sender().ep(), expected_data, size,
(uintptr_t)target_ptr, rkey, ¶m);
}
ucs_status_ptr_t do_get_iov(size_t size, void *target_ptr, ucp_rkey_h rkey,
void *expected_data, ucp_request_param_t *param,
ucp_dt_iov_t *iov, size_t iov_count,
void * /*arg*/)
{
if (iov_count > 0) {
init_iov(size, iov, iov_count, expected_data);
}
return ucp_get_nbx(sender().ep(), iov, iov_count, (uintptr_t)target_ptr,
rkey, param);
}
void test_message_sizes(send_func_t send_func, size_t min_size,
size_t max_size, ucs_memory_type_t send_mem_type,
ucs_memory_type_t target_mem_type,
unsigned mem_map_flags) {
ucs::detail::message_stream ms("INFO");
ucs_assert(min_size <= max_size);
ms << ucs_memory_type_names[send_mem_type] << "->" <<
ucs_memory_type_names[target_mem_type] << " ";
if (mem_map_flags & UCP_MEM_MAP_NONBLOCK) {
ms << "map_nb ";
}
/* Test different random sizes */
for (size_t current_max_size = min_size; current_max_size <= max_size;
current_max_size *= 4) {
size_t size = min_size;
if (min_size < current_max_size) {
size += ucs::rand() % (current_max_size - min_size);
}
unsigned num_iters = ucs_min(100, max_size / (size + 1));
num_iters = ucs_max(1, num_iters / ucs::test_time_multiplier());
ms << num_iters << "x" << size << " ";
fflush(stdout);
ucs_memory_type_t mem_types[] = {send_mem_type, target_mem_type};
test_xfer(send_func, size, num_iters, 1, send_mem_type,
target_mem_type, mem_map_flags, is_ep_flush(), mem_types);
if (HasFailure() || (num_errors() > 0)) {
break;
}
}
}
bool is_ep_flush() {
return get_variant_value() & FLUSH_EP;
}
};
UCS_TEST_P(test_ucp_rma, put_blocking) {
test_mem_types(static_cast<send_func_t>(&test_ucp_rma::put_b));
}
UCS_TEST_P(test_ucp_rma, put_nonblocking) {
test_mem_types(static_cast<send_func_t>(&test_ucp_rma::put_nbi));
}
UCS_TEST_SKIP_COND_P(test_ucp_rma, put_nonblocking_iov_zcopy, !enable_proto(),
"ZCOPY_THRESH=0") {
if (!sender().has_lane_with_caps(UCT_IFACE_FLAG_PUT_ZCOPY)) {
UCS_TEST_SKIP_R("put_zcopy is not supported");
}
test_mem_types(static_cast<send_func_t>(&test_ucp_rma::put_nbi_iov), 2000,
64 * UCS_KBYTE);
}
UCS_TEST_P(test_ucp_rma, get_blocking) {
test_mem_types(static_cast<send_func_t>(&test_ucp_rma::get_b));
}
UCS_TEST_P(test_ucp_rma, get_nonblocking) {
test_mem_types(static_cast<send_func_t>(&test_ucp_rma::get_nbi));
}
UCS_TEST_SKIP_COND_P(test_ucp_rma, get_nonblocking_iov_zcopy, !enable_proto(),
"ZCOPY_THRESH=0") {
if (!sender().has_lane_with_caps(UCT_IFACE_FLAG_GET_ZCOPY)) {
UCS_TEST_SKIP_R("put_zcopy is not supported");
}
test_mem_types(static_cast<send_func_t>(&test_ucp_rma::get_nbi_iov), 2000,
64 * UCS_KBYTE);
}
UCS_TEST_P(test_ucp_rma, get_blocking_zcopy, "ZCOPY_THRESH=0") {
/* test get_zcopy minimal message length is respected */
test_mem_types(static_cast<send_func_t>(&test_ucp_rma::get_b), 128,
64 * UCS_KBYTE);
}
UCP_INSTANTIATE_TEST_CASE_GPU_AWARE(test_ucp_rma)
|