1 /**
2 * Copyright (C) Mellanox Technologies Ltd. 2001-2017. ALL RIGHTS RESERVED.
3 *
4 * See file LICENSE for terms.
5 */
6
7 #include "test_ucp_tag.h"
8
9
10 class test_ucp_tag_perf : public test_ucp_tag {
11 public:
init()12 virtual void init() {
13 if (RUNNING_ON_VALGRIND) {
14 UCS_TEST_SKIP_R("valgrind");
15 }
16 test_ucp_tag::init();
17 }
18
19 protected:
20 static const size_t COUNT = 8192;
21 static const ucp_tag_t TAG_MASK = 0xffffffffffffffffUL;
22
23 double check_perf(size_t count, bool is_exp);
24 void check_scalability(double max_growth, bool is_exp);
25 void do_sends(size_t count);
26 };
27
check_perf(size_t count,bool is_exp)28 double test_ucp_tag_perf::check_perf(size_t count, bool is_exp)
29 {
30 ucs_time_t start_time;
31
32 if (is_exp) {
33 std::vector<request*> rreqs;
34
35 for (size_t i = 0; i < count; ++i) {
36 request *rreq = recv_nb(NULL, 0, DATATYPE, i, TAG_MASK);
37 assert(!UCS_PTR_IS_ERR(rreq));
38 EXPECT_FALSE(rreq->completed);
39 rreqs.push_back(rreq);
40 }
41
42 start_time = ucs_get_time();
43 do_sends(count);
44 while (!rreqs.empty()) {
45 request *rreq = rreqs.back();
46 rreqs.pop_back();
47 wait_and_validate(rreq);
48 }
49 } else {
50 ucp_tag_recv_info_t info;
51
52 send_b(NULL, 0, DATATYPE, 0xdeadbeef);
53 do_sends(count);
54 recv_b(NULL, 0, DATATYPE, 0xdeadbeef, TAG_MASK, &info);
55
56 start_time = ucs_get_time();
57 for (size_t i = 0; i < count; ++i) {
58 recv_b(NULL, 0, DATATYPE, i, TAG_MASK, &info);
59 }
60 }
61
62 return ucs_time_to_sec(ucs_get_time() - start_time) / count;
63 }
64
do_sends(size_t count)65 void test_ucp_tag_perf::do_sends(size_t count)
66 {
67 size_t i = count;
68 while (i > 0) {
69 --i;
70 send_b(NULL, 0, DATATYPE, i);
71 }
72 }
73
check_scalability(double max_growth,bool is_exp)74 void test_ucp_tag_perf::check_scalability(double max_growth, bool is_exp)
75 {
76 double prev_time = 0.0, total_growth = 0.0, avg_growth;
77 size_t n = 0;
78
79 for (int i = 0; i < (ucs::perf_retry_count + 1); ++i) {
80
81 /* Estimate by how much the tag matching time grows when the matching queue
82 * length grows by 2x. A result close to 1.0 means O(1) scalability (which
83 * is good), while a result of 2.0 or higher means O(n) or higher.
84 */
85 for (size_t count = 1; count <= COUNT; count *= 2) {
86 size_t iters = 10 * ucs_max(1ul, COUNT / count);
87 double total_time = 0;
88 for (size_t i = 0; i < iters; ++i) {
89 total_time += check_perf(count, is_exp);
90 }
91
92 double time = total_time / iters;
93 if (count >= 16) {
94 /* don't measure first few iterations - warmup */
95 total_growth += (time / prev_time);
96 ++n;
97 }
98 prev_time = time;
99 }
100
101 avg_growth = total_growth / n;
102 UCS_TEST_MESSAGE << "Average growth: " << avg_growth;
103
104 if (!ucs::perf_retry_count) {
105 UCS_TEST_MESSAGE << "not validating performance";
106 return; /* Skip */
107 } else if (avg_growth < max_growth) {
108 return; /* Success */
109 } else {
110 ucs::safe_sleep(ucs::perf_retry_interval);
111 }
112 }
113
114 ADD_FAILURE() << "Tag matching is not scalable";
115 }
116
UCS_TEST_P(test_ucp_tag_perf,multi_exp)117 UCS_TEST_P(test_ucp_tag_perf, multi_exp) {
118 check_scalability(1.5, true);
119 }
120
UCS_TEST_P(test_ucp_tag_perf,multi_unexp)121 UCS_TEST_P(test_ucp_tag_perf, multi_unexp) {
122 check_scalability(1.5, false);
123 }
124
125 UCP_INSTANTIATE_TEST_CASE(test_ucp_tag_perf)
126