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 printf("Cycles per division(normal) : %3.2f\n", 75 ((double)tot_cyc_n)/i); 76 printf("Cycles per division(reciprocal) : %3.2f\n\n", 77 ((double)tot_cyc_r)/i); 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 printf("Cycles per division(normal) : %3.2f\n", 115 ((double)tot_cyc_n)/i); 116 printf("Cycles per division(reciprocal) : %3.2f\n\n", 117 ((double)tot_cyc_r)/i); 118 119 tot_cyc_n = 0; 120 tot_cyc_r = 0; 121 122 printf("Validating unsigned 64bit division with 32bit divisor.\n"); 123 for (i = 0; i < MAX_ITERATIONS; i++) { 124 /* Change divisor every DIVIDE_ITER iterations. */ 125 if (i % DIVIDE_ITER == 0) { 126 divisor_u64 = rte_rand() >> 32; 127 reci_u64 = rte_reciprocal_value_u64(divisor_u64); 128 } 129 130 dividend_u64 = rte_rand(); 131 132 start_cyc = rte_rdtsc(); 133 nresult_u64 = dividend_u64 / divisor_u64; 134 split_cyc = rte_rdtsc(); 135 rresult_u64 = rte_reciprocal_divide_u64(dividend_u64, 136 &reci_u64); 137 end_cyc = rte_rdtsc(); 138 139 tot_cyc_n += split_cyc - start_cyc; 140 tot_cyc_r += end_cyc - split_cyc; 141 if (nresult_u64 != rresult_u64) { 142 printf("Division failed, expected %"PRIu64" " 143 "result %"PRIu64"", 144 nresult_u64, rresult_u64); 145 result = 1; 146 break; 147 } 148 } 149 150 printf("64bit Division results:\n"); 151 printf("Total number of cycles normal division : %"PRIu64"\n", 152 tot_cyc_n); 153 printf("Total number of cycles reciprocal division : %"PRIu64"\n", 154 tot_cyc_r); 155 printf("Cycles per division(normal) : %3.2f\n", 156 ((double)tot_cyc_n)/i); 157 printf("Cycles per division(reciprocal) : %3.2f\n\n", 158 ((double)tot_cyc_r)/i); 159 160 tot_cyc_n = 0; 161 tot_cyc_r = 0; 162 163 printf("Validating division by power of 2.\n"); 164 for (i = 0; i < 64; i++) { 165 divisor_u64 = 1ull << i; 166 reci_u64 = rte_reciprocal_value_u64(divisor_u64); 167 168 dividend_u64 = rte_rand(); 169 170 start_cyc = rte_rdtsc(); 171 nresult_u64 = dividend_u64 / divisor_u64; 172 split_cyc = rte_rdtsc(); 173 rresult_u64 = rte_reciprocal_divide_u64(dividend_u64, 174 &reci_u64); 175 end_cyc = rte_rdtsc(); 176 177 tot_cyc_n += split_cyc - start_cyc; 178 tot_cyc_r += end_cyc - split_cyc; 179 if (nresult_u64 != rresult_u64) { 180 printf("Division 64 failed, %"PRIu64"/%"PRIu64" = " 181 "expected %"PRIu64" result %"PRIu64"\n", 182 dividend_u64, divisor_u64, 183 nresult_u64, rresult_u64); 184 result = 1; 185 break; 186 } 187 } 188 printf("64bit Division results:\n"); 189 printf("Total number of cycles normal division : %"PRIu64"\n", 190 tot_cyc_n); 191 printf("Total number of cycles reciprocal division : %"PRIu64"\n", 192 tot_cyc_r); 193 printf("Cycles per division(normal) : %3.2f\n", 194 ((double)tot_cyc_n)/i); 195 printf("Cycles per division(reciprocal) : %3.2f\n", 196 ((double)tot_cyc_r)/i); 197 198 return result; 199 } 200 201 REGISTER_TEST_COMMAND(reciprocal_division_perf, test_reciprocal_division_perf); 202