1 /**
2 * Copyright (C) Mellanox Technologies Ltd. 2020.  ALL RIGHTS RESERVED.
3 *
4 * See file LICENSE for terms.
5 */
6 
7 #include "test_ucp_tag.h"
8 #include <common/mem_buffer.h>
9 
10 #include "ucp_datatype.h"
11 
12 extern "C" {
13 #include <ucp/core/ucp_ep.inl>
14 #include <ucs/datastruct/queue.h>
15 }
16 
17 #include <iostream>
18 
19 
20 class test_ucp_tag_mem_type: public test_ucp_tag {
21 public:
22     enum {
23             VARIANT_DEFAULT     = UCS_BIT(0),
24             VARIANT_GDR_OFF     = UCS_BIT(1),
25             VARIANT_TAG_OFFLOAD = UCS_BIT(2),
26             VARIANT_MAX         = UCS_BIT(3)
27     };
28 
init()29     void init() {
30         int mem_type_pair_index = GetParam().variant % mem_type_pairs.size();
31         int varient_index       = GetParam().variant / mem_type_pairs.size();
32 
33         if (varient_index & VARIANT_GDR_OFF) {
34             m_env.push_back(new ucs::scoped_setenv("UCX_IB_GPU_DIRECT_RDMA", "n"));
35         }
36 
37         if (varient_index & VARIANT_TAG_OFFLOAD) {
38             enable_tag_mp_offload();
39 
40             if (RUNNING_ON_VALGRIND) {
41                 m_env.push_back(new ucs::scoped_setenv("UCX_RC_TM_SEG_SIZE",  "8k"));
42                 m_env.push_back(new ucs::scoped_setenv("UCX_TCP_RX_SEG_SIZE", "8k"));
43             }
44         }
45 
46         m_send_mem_type  = mem_type_pairs[mem_type_pair_index][0];
47         m_recv_mem_type  = mem_type_pairs[mem_type_pair_index][1];
48 
49         modify_config("MAX_EAGER_LANES", "2");
50         modify_config("MAX_RNDV_LANES",  "2");
51 
52         test_ucp_tag::init();
53     }
54 
cleanup()55     void cleanup() {
56         test_ucp_tag::cleanup();
57     }
58 
59     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)60     static enum_test_params(const ucp_params_t& ctx_params,
61                             const std::string& name,
62                             const std::string& test_case_name,
63                             const std::string& tls) {
64 
65         std::vector<ucp_test_param> result;
66         int count = 0;
67 
68         for (int i = 0; i < VARIANT_MAX; i++) {
69             for (std::vector<std::vector<ucs_memory_type_t> >::const_iterator iter =
70                  mem_type_pairs.begin(); iter != mem_type_pairs.end(); ++iter) {
71                 generate_test_params_variant(ctx_params, name, test_case_name + "/" +
72                                              std::string(ucs_memory_type_names[(*iter)[0]]) +
73                                              "<->" + std::string(ucs_memory_type_names[(*iter)[1]]),
74                                              tls, count++, result);
75             }
76         }
77 
78         return result;
79     }
80 
81     static std::vector<std::vector<ucs_memory_type_t> > mem_type_pairs;
82 
83 protected:
84 
85     size_t do_xfer(const void *sendbuf, void *recvbuf, size_t count,
86                    ucp_datatype_t send_dt, ucp_datatype_t recv_dt,
87                    bool expected, bool truncated, bool extended);
88 
89     ucs_memory_type_t m_send_mem_type;
90     ucs_memory_type_t m_recv_mem_type;
91 
92 private:
93 
94     static const uint64_t SENDER_TAG = 0x111337;
95     static const uint64_t RECV_MASK  = 0xffff;
96     static const uint64_t RECV_TAG   = 0x1337;
97 };
98 
99 std::vector<std::vector<ucs_memory_type_t> >
100 test_ucp_tag_mem_type::mem_type_pairs = ucs::supported_mem_type_pairs();
101 
do_xfer(const void * sendbuf,void * recvbuf,size_t count,ucp_datatype_t send_dt,ucp_datatype_t recv_dt,bool expected,bool truncated,bool extended)102 size_t test_ucp_tag_mem_type::do_xfer(const void *sendbuf, void *recvbuf,
103                                   size_t count, ucp_datatype_t send_dt,
104                                   ucp_datatype_t recv_dt, bool expected,
105                                   bool truncated, bool extended)
106 {
107     size_t recv_count = count;
108     size_t send_count = count;
109     size_t recvd      = 0;
110     request *rreq, *sreq;
111 
112     if (truncated) {
113         recv_count /= 2;
114     }
115 
116     if (extended) {
117         send_count /= 2;
118     }
119 
120     if (expected) {
121         rreq = recv_nb(recvbuf, recv_count, recv_dt, RECV_TAG, RECV_MASK);
122         sreq = send_nb(sendbuf, send_count, send_dt, SENDER_TAG);
123     } else {
124         sreq = send_nb(sendbuf, send_count, send_dt, SENDER_TAG);
125 
126         wait_for_unexpected_msg(receiver().worker(), 10.0);
127 
128         rreq = recv_nb(recvbuf, recv_count, recv_dt, RECV_TAG, RECV_MASK);
129     }
130 
131     /* progress both sender and receiver */
132     wait(rreq);
133     if (sreq != NULL) {
134         wait(sreq);
135         request_release(sreq);
136     }
137 
138     recvd = rreq->info.length;
139     if (!truncated) {
140         EXPECT_UCS_OK(rreq->status);
141         EXPECT_EQ((ucp_tag_t)SENDER_TAG, rreq->info.sender_tag);
142     } else {
143         EXPECT_EQ(UCS_ERR_MESSAGE_TRUNCATED, rreq->status);
144     }
145 
146     request_release(rreq);
147     return recvd;
148 };
149 
UCS_TEST_P(test_ucp_tag_mem_type,basic)150 UCS_TEST_P(test_ucp_tag_mem_type, basic)
151 {
152     ucp_datatype_t type = ucp_dt_make_contig(1);
153 
154     UCS_TEST_MESSAGE << "TEST: "
155                      << ucs_memory_type_names[m_send_mem_type] << " <-> "
156                      << ucs_memory_type_names[m_recv_mem_type];
157 
158     for (unsigned i = 1; i <= 7; ++i) {
159         size_t max = (long)pow(10.0, i);
160         size_t length = ucs::rand() % max + 1;
161 
162         mem_buffer m_recv_mem_buf(length, m_recv_mem_type);
163         mem_buffer m_send_mem_buf(length, m_send_mem_type);
164 
165         mem_buffer::pattern_fill(m_recv_mem_buf.ptr(), m_recv_mem_buf.size(),
166                                  1, m_recv_mem_buf.mem_type());
167 
168         mem_buffer::pattern_fill(m_send_mem_buf.ptr(), m_send_mem_buf.size(),
169                                  2, m_send_mem_buf.mem_type());
170 
171         size_t recvd = do_xfer(m_send_mem_buf.ptr(), m_recv_mem_buf.ptr(),
172                                length, type, type, true, false, false);
173         ASSERT_EQ(length, recvd);
174         mem_buffer::pattern_check(m_recv_mem_buf.ptr(), length,
175                                   2, m_recv_mem_buf.mem_type());
176     }
177 }
178 
UCS_TEST_P(test_ucp_tag_mem_type,xfer_mismatch_length)179 UCS_TEST_P(test_ucp_tag_mem_type, xfer_mismatch_length)
180 {
181     ucp_datatype_t type = ucp_dt_make_contig(1);
182     size_t length = ucs::rand() % ((ssize_t)pow(10.0, 7));
183 
184     UCS_TEST_MESSAGE << "TEST: "
185                      << ucs_memory_type_names[m_send_mem_type] << " <-> "
186                      << ucs_memory_type_names[m_recv_mem_type] << " length: "
187                      << length;
188 
189     mem_buffer m_recv_mem_buf(length, m_recv_mem_type);
190     mem_buffer m_send_mem_buf(length, m_send_mem_type);
191 
192     mem_buffer::pattern_fill(m_recv_mem_buf.ptr(), m_recv_mem_buf.size(),
193                              1, m_recv_mem_buf.mem_type());
194 
195     mem_buffer::pattern_fill(m_send_mem_buf.ptr(), m_send_mem_buf.size(),
196                              2, m_send_mem_buf.mem_type());
197 
198     /* truncated */
199     do_xfer(m_send_mem_buf.ptr(), m_recv_mem_buf.ptr(),
200             length, type, type, true, true, false);
201 
202     /* extended recv buffer */
203     size_t recvd = do_xfer(m_send_mem_buf.ptr(), m_recv_mem_buf.ptr(),
204                            length, type, type, true, false, true);
205     ASSERT_EQ(length / 2,  recvd);
206 
207 }
208 
209 
210 UCP_INSTANTIATE_TEST_CASE_GPU_AWARE(test_ucp_tag_mem_type);
211