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 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 rte_srand(rte_rdtsc()); 41 42 printf("Validating unsigned 32bit division.\n"); 43 for (i = 0; i < MAX_ITERATIONS; i++) { 44 /* Change divisor every DIVIDE_ITER iterations. */ 45 if (i % DIVIDE_ITER == 0) { 46 divisor_u32 = rte_rand(); 47 reci_u32 = rte_reciprocal_value(divisor_u32); 48 } 49 50 dividend_u32 = rte_rand(); 51 52 start_cyc = rte_rdtsc(); 53 nresult_u32 = dividend_u32 / divisor_u32; 54 split_cyc = rte_rdtsc(); 55 rresult_u32 = rte_reciprocal_divide(dividend_u32, 56 reci_u32); 57 end_cyc = rte_rdtsc(); 58 59 tot_cyc_n += split_cyc - start_cyc; 60 tot_cyc_r += end_cyc - split_cyc; 61 if (nresult_u32 != rresult_u32) { 62 printf("Division failed, expected %"PRIu32" " 63 "result %"PRIu32"", 64 nresult_u32, rresult_u32); 65 result = 1; 66 break; 67 } 68 } 69 printf("32bit Division results:\n"); 70 printf("Total number of cycles normal division : %"PRIu64"\n", 71 tot_cyc_n); 72 printf("Total number of cycles reciprocal division : %"PRIu64"\n", 73 tot_cyc_r); 74 if (i != 0) { 75 printf("Cycles per division(normal) : %3.2f\n", 76 ((double)tot_cyc_n)/i); 77 printf("Cycles per division(reciprocal) : %3.2f\n\n", 78 ((double)tot_cyc_r)/i); 79 } 80 81 tot_cyc_n = 0; 82 tot_cyc_r = 0; 83 84 printf("Validating unsigned 64bit division.\n"); 85 for (i = 0; i < MAX_ITERATIONS; i++) { 86 /* Change divisor every DIVIDE_ITER iterations. */ 87 if (i % DIVIDE_ITER == 0) { 88 divisor_u64 = rte_rand(); 89 reci_u64 = rte_reciprocal_value_u64(divisor_u64); 90 } 91 92 dividend_u64 = rte_rand(); 93 94 start_cyc = rte_rdtsc(); 95 nresult_u64 = dividend_u64 / divisor_u64; 96 split_cyc = rte_rdtsc(); 97 rresult_u64 = rte_reciprocal_divide_u64(dividend_u64, 98 &reci_u64); 99 end_cyc = rte_rdtsc(); 100 101 tot_cyc_n += split_cyc - start_cyc; 102 tot_cyc_r += end_cyc - split_cyc; 103 if (nresult_u64 != rresult_u64) { 104 printf("Division failed, expected %"PRIu64" " 105 "result %"PRIu64"", 106 nresult_u64, rresult_u64); 107 result = 1; 108 break; 109 } 110 } 111 printf("64bit Division results:\n"); 112 printf("Total number of cycles normal division : %"PRIu64"\n", 113 tot_cyc_n); 114 printf("Total number of cycles reciprocal division : %"PRIu64"\n", 115 tot_cyc_r); 116 if (i != 0) { 117 printf("Cycles per division(normal) : %3.2f\n", 118 ((double)tot_cyc_n)/i); 119 printf("Cycles per division(reciprocal) : %3.2f\n\n", 120 ((double)tot_cyc_r)/i); 121 } 122 tot_cyc_n = 0; 123 tot_cyc_r = 0; 124 125 printf("Validating unsigned 64bit division with 32bit divisor.\n"); 126 for (i = 0; i < MAX_ITERATIONS; i++) { 127 /* Change divisor every DIVIDE_ITER iterations. */ 128 if (i % DIVIDE_ITER == 0) { 129 divisor_u64 = rte_rand() >> 32; 130 reci_u64 = rte_reciprocal_value_u64(divisor_u64); 131 } 132 133 dividend_u64 = rte_rand(); 134 135 start_cyc = rte_rdtsc(); 136 nresult_u64 = dividend_u64 / divisor_u64; 137 split_cyc = rte_rdtsc(); 138 rresult_u64 = rte_reciprocal_divide_u64(dividend_u64, 139 &reci_u64); 140 end_cyc = rte_rdtsc(); 141 142 tot_cyc_n += split_cyc - start_cyc; 143 tot_cyc_r += end_cyc - split_cyc; 144 if (nresult_u64 != rresult_u64) { 145 printf("Division failed, expected %"PRIu64" " 146 "result %"PRIu64"", 147 nresult_u64, rresult_u64); 148 result = 1; 149 break; 150 } 151 } 152 153 printf("64bit Division results:\n"); 154 printf("Total number of cycles normal division : %"PRIu64"\n", 155 tot_cyc_n); 156 printf("Total number of cycles reciprocal division : %"PRIu64"\n", 157 tot_cyc_r); 158 if (i != 0) { 159 printf("Cycles per division(normal) : %3.2f\n", 160 ((double)tot_cyc_n)/i); 161 printf("Cycles per division(reciprocal) : %3.2f\n\n", 162 ((double)tot_cyc_r)/i); 163 } 164 165 tot_cyc_n = 0; 166 tot_cyc_r = 0; 167 168 printf("Validating division by power of 2.\n"); 169 for (i = 0; i < 64; i++) { 170 divisor_u64 = 1ull << i; 171 reci_u64 = rte_reciprocal_value_u64(divisor_u64); 172 173 dividend_u64 = rte_rand(); 174 175 start_cyc = rte_rdtsc(); 176 nresult_u64 = dividend_u64 / divisor_u64; 177 split_cyc = rte_rdtsc(); 178 rresult_u64 = rte_reciprocal_divide_u64(dividend_u64, 179 &reci_u64); 180 end_cyc = rte_rdtsc(); 181 182 tot_cyc_n += split_cyc - start_cyc; 183 tot_cyc_r += end_cyc - split_cyc; 184 if (nresult_u64 != rresult_u64) { 185 printf("Division 64 failed, %"PRIu64"/%"PRIu64" = " 186 "expected %"PRIu64" result %"PRIu64"\n", 187 dividend_u64, divisor_u64, 188 nresult_u64, rresult_u64); 189 result = 1; 190 break; 191 } 192 } 193 printf("64bit Division results:\n"); 194 printf("Total number of cycles normal division : %"PRIu64"\n", 195 tot_cyc_n); 196 printf("Total number of cycles reciprocal division : %"PRIu64"\n", 197 tot_cyc_r); 198 if (i != 0) { 199 printf("Cycles per division(normal) : %3.2f\n", 200 ((double)tot_cyc_n)/i); 201 printf("Cycles per division(reciprocal) : %3.2f\n", 202 ((double)tot_cyc_r)/i); 203 } 204 205 return result; 206 } 207 208 REGISTER_TEST_COMMAND(reciprocal_division_perf, test_reciprocal_division_perf); 209