1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2017 Cavium, Inc
3 */
4
5 #include "test.h"
6
7 #include <stdio.h>
8 #include <unistd.h>
9 #include <inttypes.h>
10
11 #include <rte_common.h>
12 #include <rte_cycles.h>
13 #include <rte_random.h>
14 #include <rte_reciprocal.h>
15
16 #define MAX_ITERATIONS (1ULL << 32)
17 #define DIVIDE_ITER (1ULL << 28)
18
19 static int
test_reciprocal_division_perf(void)20 test_reciprocal_division_perf(void)
21 {
22 int result = 0;
23 uint32_t divisor_u32 = 0;
24 uint32_t dividend_u32;
25 uint64_t divisor_u64 = 0;
26 uint64_t dividend_u64;
27 volatile uint32_t nresult_u32;
28 volatile uint32_t rresult_u32;
29 volatile uint64_t nresult_u64;
30 volatile uint64_t rresult_u64;
31 uint64_t start_cyc;
32 uint64_t split_cyc;
33 uint64_t end_cyc;
34 uint64_t tot_cyc_n = 0;
35 uint64_t tot_cyc_r = 0;
36 uint64_t i;
37 struct rte_reciprocal reci_u32 = {0};
38 struct rte_reciprocal_u64 reci_u64 = {0};
39
40 printf("Validating unsigned 32bit division.\n");
41 for (i = 0; i < MAX_ITERATIONS; i++) {
42 /* Change divisor every DIVIDE_ITER iterations. */
43 if (i % DIVIDE_ITER == 0) {
44 divisor_u32 = rte_rand();
45 reci_u32 = rte_reciprocal_value(divisor_u32);
46 }
47
48 dividend_u32 = rte_rand();
49
50 start_cyc = rte_rdtsc();
51 nresult_u32 = dividend_u32 / divisor_u32;
52 split_cyc = rte_rdtsc();
53 rresult_u32 = rte_reciprocal_divide(dividend_u32,
54 reci_u32);
55 end_cyc = rte_rdtsc();
56
57 tot_cyc_n += split_cyc - start_cyc;
58 tot_cyc_r += end_cyc - split_cyc;
59 if (nresult_u32 != rresult_u32) {
60 printf("Division failed, expected %"PRIu32" "
61 "result %"PRIu32"",
62 nresult_u32, rresult_u32);
63 result = 1;
64 break;
65 }
66 }
67 printf("32bit Division results:\n");
68 printf("Total number of cycles normal division : %"PRIu64"\n",
69 tot_cyc_n);
70 printf("Total number of cycles reciprocal division : %"PRIu64"\n",
71 tot_cyc_r);
72 if (i != 0) {
73 printf("Cycles per division(normal) : %3.2f\n",
74 ((double)tot_cyc_n)/i);
75 printf("Cycles per division(reciprocal) : %3.2f\n\n",
76 ((double)tot_cyc_r)/i);
77 }
78
79 tot_cyc_n = 0;
80 tot_cyc_r = 0;
81
82 printf("Validating unsigned 64bit division.\n");
83 for (i = 0; i < MAX_ITERATIONS; i++) {
84 /* Change divisor every DIVIDE_ITER iterations. */
85 if (i % DIVIDE_ITER == 0) {
86 divisor_u64 = rte_rand();
87 reci_u64 = rte_reciprocal_value_u64(divisor_u64);
88 }
89
90 dividend_u64 = rte_rand();
91
92 start_cyc = rte_rdtsc();
93 nresult_u64 = dividend_u64 / divisor_u64;
94 split_cyc = rte_rdtsc();
95 rresult_u64 = rte_reciprocal_divide_u64(dividend_u64,
96 &reci_u64);
97 end_cyc = rte_rdtsc();
98
99 tot_cyc_n += split_cyc - start_cyc;
100 tot_cyc_r += end_cyc - split_cyc;
101 if (nresult_u64 != rresult_u64) {
102 printf("Division failed, expected %"PRIu64" "
103 "result %"PRIu64"",
104 nresult_u64, rresult_u64);
105 result = 1;
106 break;
107 }
108 }
109 printf("64bit Division results:\n");
110 printf("Total number of cycles normal division : %"PRIu64"\n",
111 tot_cyc_n);
112 printf("Total number of cycles reciprocal division : %"PRIu64"\n",
113 tot_cyc_r);
114 if (i != 0) {
115 printf("Cycles per division(normal) : %3.2f\n",
116 ((double)tot_cyc_n)/i);
117 printf("Cycles per division(reciprocal) : %3.2f\n\n",
118 ((double)tot_cyc_r)/i);
119 }
120 tot_cyc_n = 0;
121 tot_cyc_r = 0;
122
123 printf("Validating unsigned 64bit division with 32bit divisor.\n");
124 for (i = 0; i < MAX_ITERATIONS; i++) {
125 /* Change divisor every DIVIDE_ITER iterations. */
126 if (i % DIVIDE_ITER == 0) {
127 divisor_u64 = rte_rand() >> 32;
128 reci_u64 = rte_reciprocal_value_u64(divisor_u64);
129 }
130
131 dividend_u64 = rte_rand();
132
133 start_cyc = rte_rdtsc();
134 nresult_u64 = dividend_u64 / divisor_u64;
135 split_cyc = rte_rdtsc();
136 rresult_u64 = rte_reciprocal_divide_u64(dividend_u64,
137 &reci_u64);
138 end_cyc = rte_rdtsc();
139
140 tot_cyc_n += split_cyc - start_cyc;
141 tot_cyc_r += end_cyc - split_cyc;
142 if (nresult_u64 != rresult_u64) {
143 printf("Division failed, expected %"PRIu64" "
144 "result %"PRIu64"",
145 nresult_u64, rresult_u64);
146 result = 1;
147 break;
148 }
149 }
150
151 printf("64bit Division results:\n");
152 printf("Total number of cycles normal division : %"PRIu64"\n",
153 tot_cyc_n);
154 printf("Total number of cycles reciprocal division : %"PRIu64"\n",
155 tot_cyc_r);
156 if (i != 0) {
157 printf("Cycles per division(normal) : %3.2f\n",
158 ((double)tot_cyc_n)/i);
159 printf("Cycles per division(reciprocal) : %3.2f\n\n",
160 ((double)tot_cyc_r)/i);
161 }
162
163 tot_cyc_n = 0;
164 tot_cyc_r = 0;
165
166 printf("Validating division by power of 2.\n");
167 for (i = 0; i < 64; i++) {
168 divisor_u64 = 1ull << i;
169 reci_u64 = rte_reciprocal_value_u64(divisor_u64);
170
171 dividend_u64 = rte_rand();
172
173 start_cyc = rte_rdtsc();
174 nresult_u64 = dividend_u64 / divisor_u64;
175 split_cyc = rte_rdtsc();
176 rresult_u64 = rte_reciprocal_divide_u64(dividend_u64,
177 &reci_u64);
178 end_cyc = rte_rdtsc();
179
180 tot_cyc_n += split_cyc - start_cyc;
181 tot_cyc_r += end_cyc - split_cyc;
182 if (nresult_u64 != rresult_u64) {
183 printf("Division 64 failed, %"PRIu64"/%"PRIu64" = "
184 "expected %"PRIu64" result %"PRIu64"\n",
185 dividend_u64, divisor_u64,
186 nresult_u64, rresult_u64);
187 result = 1;
188 break;
189 }
190 }
191 printf("64bit Division results:\n");
192 printf("Total number of cycles normal division : %"PRIu64"\n",
193 tot_cyc_n);
194 printf("Total number of cycles reciprocal division : %"PRIu64"\n",
195 tot_cyc_r);
196 if (i != 0) {
197 printf("Cycles per division(normal) : %3.2f\n",
198 ((double)tot_cyc_n)/i);
199 printf("Cycles per division(reciprocal) : %3.2f\n",
200 ((double)tot_cyc_r)/i);
201 }
202
203 return result;
204 }
205
206 REGISTER_PERF_TEST(reciprocal_division_perf, test_reciprocal_division_perf);
207