Skip to content

Commit f4a288d

Browse files
committed
Check-in intel libbid benchmark file
1 parent 6efa129 commit f4a288d

File tree

1 file changed

+359
-0
lines changed

1 file changed

+359
-0
lines changed

test/benchmark_libbid.c

Lines changed: 359 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,359 @@
1+
// Copyright 2024 Matt Borland
2+
// Distributed under the Boost Software License, Version 1.0.
3+
// https://www.boost.org/LICENSE_1_0.txt
4+
5+
#define _POSIX_C_SOURCE 199309L
6+
#define DECIMAL_GLOBAL_ROUNDING 1
7+
#define DECIMAL_GLOBAL_EXCEPTION_FLAGS 1
8+
9+
#include <stdio.h>
10+
#include <stdlib.h>
11+
#include <stdint.h>
12+
#include <time.h>
13+
#include <inttypes.h>
14+
#include <float.h>
15+
#include <fenv.h>
16+
17+
typedef uint32_t Decimal32;
18+
typedef uint64_t Decimal64;
19+
#include "../LIBRARY/src/bid_conf.h"
20+
#include "../LIBRARY/src/bid_functions.h"
21+
typedef BID_UINT128 Decimal128;
22+
23+
#define K 20000000
24+
#define N 5
25+
26+
uint32_t random_uint32(void)
27+
{
28+
uint32_t r = 0;
29+
for (int i = 0; i < 2; i++)
30+
{
31+
r = (r << 16) | (rand() & 0xFFFF);
32+
}
33+
34+
return r;
35+
}
36+
37+
uint64_t random_uint64(void)
38+
{
39+
uint32_t r = 0;
40+
for (int i = 0; i < 4; i++)
41+
{
42+
r = (r << 16) | (rand() & 0xFFFF);
43+
}
44+
45+
return r;
46+
}
47+
48+
__attribute__ ((noinline)) void generate_vector_32(Decimal32* buffer, size_t buffer_len)
49+
{
50+
for (size_t i = 0; i < buffer_len; ++i)
51+
{
52+
buffer[i] = bid32_from_uint32(random_uint32() % 100);
53+
}
54+
}
55+
56+
__attribute__ ((noinline)) void test_comparisons_32(Decimal32* data, const char* label)
57+
{
58+
struct timespec t1, t2;
59+
clock_gettime(CLOCK_MONOTONIC, &t1);
60+
61+
size_t s = 0;
62+
63+
for (size_t n = 0; n < N; ++n)
64+
{
65+
for (size_t k = 0; k < K - 1; ++k)
66+
{
67+
Decimal32 val1 = data[k];
68+
Decimal32 val2 = data[k + 1];
69+
70+
s += (size_t)bid32_quiet_less(val1, val2);
71+
s += (size_t)bid32_quiet_less_equal(val1, val2);
72+
s += (size_t)bid32_quiet_greater(val1, val2);
73+
s += (size_t)bid32_quiet_greater_equal(val1, val2);
74+
s += (size_t)bid32_quiet_equal(val1, val2);
75+
s += (size_t)bid32_quiet_not_equal(val1, val2);
76+
}
77+
}
78+
79+
clock_gettime(CLOCK_MONOTONIC, &t2);
80+
81+
uint64_t elapsed_time_us = (uint64_t)((t2.tv_sec - t1.tv_sec) * 1000000 + (t2.tv_nsec - t1.tv_nsec) / 1000);
82+
printf("Comparisons <%-10s >: %-10" PRIu64 " us (s=%zu)\n", label, elapsed_time_us, s);
83+
}
84+
85+
__attribute__ ((noinline)) void generate_vector_64(Decimal64* buffer, size_t buffer_len)
86+
{
87+
for (size_t i = 0; i < buffer_len; ++i)
88+
{
89+
buffer[i] = bid64_from_uint64(random_uint64() % 10000);
90+
}
91+
}
92+
93+
__attribute__ ((noinline)) void test_comparisons_64(Decimal64* data, const char* label)
94+
{
95+
struct timespec t1, t2;
96+
clock_gettime(CLOCK_MONOTONIC, &t1);
97+
98+
size_t s = 0;
99+
100+
for (size_t n = 0; n < N; ++n)
101+
{
102+
for (size_t k = 0; k < K - 1; ++k)
103+
{
104+
Decimal64 val1 = data[k];
105+
Decimal64 val2 = data[k + 1];
106+
107+
s += (size_t)bid64_quiet_less(val1, val2);
108+
s += (size_t)bid64_quiet_less_equal(val1, val2);
109+
s += (size_t)bid64_quiet_greater(val1, val2);
110+
s += (size_t)bid64_quiet_greater_equal(val1, val2);
111+
s += (size_t)bid64_quiet_equal(val1, val2);
112+
s += (size_t)bid64_quiet_not_equal(val1, val2);
113+
}
114+
}
115+
116+
clock_gettime(CLOCK_MONOTONIC, &t2);
117+
118+
uint64_t elapsed_time_us = (uint64_t)((t2.tv_sec - t1.tv_sec) * 1000000 + (t2.tv_nsec - t1.tv_nsec) / 1000);
119+
printf("Comparisons <%-10s >: %-10" PRIu64 " us (s=%zu)\n", label, elapsed_time_us, s);
120+
}
121+
122+
123+
__attribute__ ((__noinline__)) void generate_vector_128(Decimal128* buffer, size_t buffer_len)
124+
{
125+
size_t i = 0;
126+
while (i < buffer_len)
127+
{
128+
buffer[i] = bid128_from_uint64(random_uint64() % 100);
129+
++i;
130+
}
131+
}
132+
133+
__attribute__ ((__noinline__)) void test_comparisons_128(Decimal128* data, const char* label)
134+
{
135+
struct timespec t1, t2;
136+
clock_gettime(CLOCK_MONOTONIC, &t1);
137+
138+
size_t s = 0;
139+
140+
for (size_t n = 0; n < N; ++n)
141+
{
142+
for (size_t k = 0; k < K - 1; ++k)
143+
{
144+
Decimal128 val1 = data[k];
145+
Decimal128 val2 = data[k + 1];
146+
147+
s += (size_t)bid128_quiet_less(val1, val2);
148+
s += (size_t)bid128_quiet_less_equal(val1, val2);
149+
s += (size_t)bid128_quiet_greater(val1, val2);
150+
s += (size_t)bid128_quiet_greater_equal(val1, val2);
151+
s += (size_t)bid128_quiet_equal(val1, val2);
152+
s += (size_t)bid128_quiet_not_equal(val1, val2);
153+
}
154+
}
155+
156+
clock_gettime(CLOCK_MONOTONIC, &t2);
157+
158+
uint64_t elapsed_time_us = (uint64_t)((t2.tv_sec - t1.tv_sec) * 1000000 + (t2.tv_nsec - t1.tv_nsec) / 1000);
159+
printf("Comparisons <%-10s >: %-10" PRIu64 " us (s=%zu)\n", label, elapsed_time_us, s);
160+
}
161+
162+
163+
typedef Decimal32 (*operation_32)(Decimal32, Decimal32);
164+
165+
__attribute__ ((noinline)) Decimal32 add_32(Decimal32 a, Decimal32 b)
166+
{
167+
return bid32_add(a, b);
168+
}
169+
__attribute__ ((noinline)) Decimal32 sub_32(Decimal32 a, Decimal32 b)
170+
{
171+
return bid32_sub(a, b);
172+
}
173+
174+
__attribute__ ((noinline)) Decimal32 mul_32(Decimal32 a, Decimal32 b)
175+
{
176+
return bid32_mul(a, b);
177+
}
178+
179+
__attribute__ ((noinline)) Decimal32 div_32(Decimal32 a, Decimal32 b)
180+
{
181+
return bid32_div(a, b);
182+
}
183+
184+
__attribute__ ((noinline)) void test_two_element_operation_32(Decimal32* data, operation_32 op, const char* label, const char* op_label)
185+
{
186+
struct timespec t1, t2;
187+
clock_gettime(CLOCK_MONOTONIC, &t1);
188+
189+
size_t s = 0;
190+
191+
for (size_t n = 0; n < N; ++n)
192+
{
193+
for (size_t k = 0; k < K - 1; ++k)
194+
{
195+
Decimal32 val1 = data[k];
196+
Decimal32 val2 = data[k + 1];
197+
198+
s += (size_t)bid32_to_int32_int(op(val1, val2));
199+
}
200+
}
201+
202+
clock_gettime(CLOCK_MONOTONIC, &t2);
203+
204+
uint64_t elapsed_time_us = (uint64_t)((t2.tv_sec - t1.tv_sec) * 1000000 + (t2.tv_nsec - t1.tv_nsec) / 1000);
205+
printf("%-15s<%-10s >: %-10" PRIu64 " us (s=%zu)\n", op_label, label, elapsed_time_us, s);
206+
}
207+
208+
typedef Decimal64 (*operation_64)(Decimal64, Decimal64);
209+
210+
__attribute__ ((noinline)) Decimal64 add_64(Decimal64 a, Decimal64 b)
211+
{
212+
return bid64_add(a, b);
213+
}
214+
215+
__attribute__ ((noinline)) Decimal64 sub_64(Decimal64 a, Decimal64 b)
216+
{
217+
return bid64_sub(a, b);
218+
}
219+
220+
__attribute__ ((noinline)) Decimal64 mul_64(Decimal64 a, Decimal64 b)
221+
{
222+
return bid64_mul(a, b);
223+
}
224+
225+
__attribute__ ((noinline)) Decimal64 div_64(Decimal64 a, Decimal64 b)
226+
{
227+
return bid64_div(a, b);
228+
}
229+
230+
__attribute__ ((noinline)) void test_two_element_operation_64(Decimal64* data, operation_64 op, const char* label, const char* op_label)
231+
{
232+
struct timespec t1, t2;
233+
clock_gettime(CLOCK_MONOTONIC, &t1);
234+
235+
size_t s = 0;
236+
237+
for (size_t n = 0; n < N; ++n)
238+
{
239+
for (size_t k = 0; k < K - 1; ++k)
240+
{
241+
Decimal64 val1 = data[k];
242+
Decimal64 val2 = data[k + 1];
243+
244+
s += (size_t)bid64_to_int64_int(op(val1, val2));
245+
}
246+
}
247+
248+
clock_gettime(CLOCK_MONOTONIC, &t2);
249+
250+
uint64_t elapsed_time_us = (uint64_t)((t2.tv_sec - t1.tv_sec) * 1000000 + (t2.tv_nsec - t1.tv_nsec) / 1000);
251+
printf("%-15s<%-10s >: %-10" PRIu64 " us (s=%zu)\n", op_label, label, elapsed_time_us, s);
252+
}
253+
254+
255+
typedef Decimal128 (*operation_128)(Decimal128, Decimal128);
256+
257+
__attribute__ ((__noinline__)) Decimal128 add_128(Decimal128 a, Decimal128 b)
258+
{
259+
return bid128_add(a, b);
260+
}
261+
262+
__attribute__ ((__noinline__)) Decimal128 sub_128(Decimal128 a, Decimal128 b)
263+
{
264+
return bid128_sub(a, b);
265+
}
266+
267+
__attribute__ ((__noinline__)) Decimal128 mul_128(Decimal128 a, Decimal128 b)
268+
{
269+
return bid128_mul(a, b);
270+
}
271+
272+
__attribute__ ((__noinline__)) Decimal128 div_128(Decimal128 a, Decimal128 b)
273+
{
274+
return bid128_div(a, b);
275+
}
276+
277+
__attribute__ ((__noinline__)) void test_two_element_operation_128(Decimal128* data, operation_128 op, const char* label, const char* op_label)
278+
{
279+
struct timespec t1, t2;
280+
clock_gettime(CLOCK_MONOTONIC, &t1);
281+
282+
size_t s = 0;
283+
284+
for (size_t n = 0; n < N; ++n)
285+
{
286+
for (size_t k = 0; k < K - 1; ++k)
287+
{
288+
Decimal128 val1 = data[k];
289+
Decimal128 val2 = data[k + 1];
290+
291+
s += (size_t)bid128_to_int64_int(op(val1, val2));
292+
}
293+
}
294+
295+
clock_gettime(CLOCK_MONOTONIC, &t2);
296+
297+
uint64_t elapsed_time_us = (uint64_t)((t2.tv_sec - t1.tv_sec) * 1000000 + (t2.tv_nsec - t1.tv_nsec) / 1000);
298+
printf("%-15s<%-10s >: %-10" PRIu64 " us (s=%zu)\n", op_label, label, elapsed_time_us, s);
299+
}
300+
301+
302+
int main()
303+
{
304+
// One time init of random number generator
305+
srand(time(NULL));
306+
307+
fedisableexcept(FE_ALL_EXCEPT);
308+
309+
Decimal32* d32_array = malloc(K * sizeof(Decimal32));
310+
Decimal64* d64_array = malloc(K * sizeof(Decimal64));
311+
Decimal128* d128_array = malloc(K * sizeof(Decimal128));
312+
313+
if (d32_array == NULL|| d64_array == NULL || d128_array == NULL)
314+
{
315+
return 1;
316+
}
317+
318+
printf("== Generating Arrays ==\n");
319+
320+
generate_vector_32(d32_array, K);
321+
generate_vector_64(d64_array, K);
322+
generate_vector_128(d128_array, K);
323+
324+
printf("===== Comparisons =====\n");
325+
326+
test_comparisons_32(d32_array, "Decimal32");
327+
test_comparisons_64(d64_array, "Decimal64");
328+
test_comparisons_128(d128_array, "Decimal128");
329+
330+
printf("\n===== Addition =====\n");
331+
332+
test_two_element_operation_32(d32_array, add_32, "Decimal32", "Addition");
333+
test_two_element_operation_64(d64_array, add_64, "Decimal64", "Addition");
334+
test_two_element_operation_128(d128_array, add_128, "Decimal128", "Addition");
335+
336+
printf("\n===== Subtraction =====\n");
337+
338+
test_two_element_operation_32(d32_array, sub_32, "Decimal32", "Subtraction");
339+
test_two_element_operation_64(d64_array, sub_64, "Decimal64", "Subtraction");
340+
test_two_element_operation_128(d128_array, sub_128, "Decimal128", "Subtraction");
341+
342+
printf("\n===== Multiplication =====\n");
343+
344+
test_two_element_operation_32(d32_array, mul_32, "Decimal32", "Multiplication");
345+
test_two_element_operation_64(d64_array, mul_64, "Decimal64", "Multiplication");
346+
test_two_element_operation_128(d128_array, mul_128, "Decimal128", "Multiplication");
347+
348+
printf("\n===== Division =====\n");
349+
350+
test_two_element_operation_32(d32_array, div_32, "Decimal32", "Division");
351+
test_two_element_operation_64(d64_array, div_64, "Decimal64", "Division");
352+
test_two_element_operation_128(d128_array, div_128, "Decimal128", "Division");
353+
354+
free(d32_array);
355+
free(d64_array);
356+
free(d128_array);
357+
358+
return 0;
359+
}

0 commit comments

Comments
 (0)