xref: /dpdk/app/test/test_reciprocal_division_perf.c (revision 2a454f84f715608ee709a4c6ba00edf2e4b62b69)
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