Skip to content

Commit fc8e8d7

Browse files
authored
Merge pull request #1283 from cppalliance/gcc_bid
2 parents c68aa53 + c280f19 commit fc8e8d7

File tree

2 files changed

+116
-32
lines changed

2 files changed

+116
-32
lines changed

doc/modules/ROOT/pages/benchmarks.adoc

Lines changed: 61 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ To run the GCC benchmarks you can use the following command: `gcc benchmark_libd
2828

2929
To run the Intel benchmarks you will need both the https://www.intel.com/content/www/us/en/developer/tools/oneapi/overview.html[Intel Compiler], and the https://www.intel.com/content/www/us/en/developer/articles/tool/intel-decimal-floating-point-math-library.html[library].
3030
You can the use the following command: `icx benchmark_libbid.c -O3 $PATH_TO_LIBBID/libbid.a -std=c17` followed by: `./a.out`
31+
You can also use `gcc` instead of `icx`.
3132

3233
NOTE: The Intel benchmarks can only be run on one of their supported architectures: IA-32, IA-64, and Intel x64
3334

@@ -92,13 +93,13 @@ Intel Compiler:
9293
| `decimal_fast128_t`
9394
| 698,945
9495
| 4.856
95-
| Intel `Decimal32`
96+
| Intel `BID_UINT32`
9697
| 2,411,294
9798
| 16.754
98-
| Intel `Decimal64`
99+
| Intel `BID_UINT64`
99100
| 3,158,422
100101
| 21.945
101-
| Intel `Decimal128`
102+
| Intel `BID_UINT128`
102103
| 3,389,883
103104
| 23.553
104105
|===
@@ -140,6 +141,15 @@ GCC:
140141
| GCC `_Decimal128`
141142
| 914,600
142143
| 14.844
144+
| Intel `BID_UINT32`
145+
| 3,718,385
146+
| 60.348
147+
| Intel `BID_UINT64`
148+
| 5,721,887
149+
| 92.865
150+
| Intel `BID_UINT128`
151+
| 7,090,648
152+
| 115.080
143153
|===
144154

145155
=== Addition
@@ -172,13 +182,13 @@ Intel Compiler:
172182
| `decimal_fast128_t`
173183
| 1,367,004
174184
| 15.092
175-
| Intel `Decimal32`
185+
| Intel `BID_UINT32`
176186
| 1,242,797
177187
| 13.721
178-
| Intel `Decimal64`
188+
| Intel `BID_UINT64`
179189
| 1,689,585
180190
| 18.653
181-
| Intel `Decimal128`
191+
| Intel `BID_UINT128`
182192
| 1,958,345
183193
| 21.620
184194
|===
@@ -220,6 +230,15 @@ GCC:
220230
| GCC `_Decimal128`
221231
| 3,368,864
222232
| 46.138
233+
| Intel `BID_UINT32`
234+
| 2,838,194
235+
| 38.879
236+
| Intel `BID_UINT64`
237+
| 3,297,652
238+
| 45.163
239+
| Intel `BID_UINT128`
240+
| 2,796,283
241+
| 38.296
223242
|===
224243

225244
=== Subtraction
@@ -252,13 +271,13 @@ Intel Compiler:
252271
| `decimal_fast128_t`
253272
| 1,212,405
254273
| 16.564
255-
| Intel `Decimal32`
274+
| Intel `BID_UINT32`
256275
| 1,922,108
257276
| 26.261
258-
| Intel `Decimal64`
277+
| Intel `BID_UINT64`
259278
| 1,793,879
260279
| 24.509
261-
| Intel `Decimal128`
280+
| Intel `BID_UINT128`
262281
| 2,397,372
263282
| 32.754
264283
|===
@@ -300,6 +319,15 @@ GCC:
300319
| GCC `_Decimal128`
301320
| 3,178,891
302321
| 10.816
322+
| Intel `BID_UINT32`
323+
| 3,762,566
324+
| 12.802
325+
| Intel `BID_UINT64`
326+
| 3,432,814
327+
| 11.680
328+
| Intel `BID_UINT128`
329+
| 3,725,534
330+
| 12.676
303331
|===
304332

305333
=== Multiplication
@@ -332,13 +360,13 @@ Intel Compiler:
332360
| `decimal_fast128_t`
333361
| 5,959,977
334362
| 81.870
335-
| Intel `Decimal32`
363+
| Intel `BID_UINT32`
336364
| 1,375,434
337365
| 18.894
338-
| Intel `Decimal64`
366+
| Intel `BID_UINT64`
339367
| 2,052,278
340368
| 28.191
341-
| Intel `Decimal128`
369+
| Intel `BID_UINT128`
342370
| 5,964,489
343371
| 81.932
344372
|===
@@ -380,6 +408,15 @@ GCC:
380408
| GCC `_Decimal128`
381409
| 7,050,299
382410
| 107.289
411+
| Intel `BID_UINT32`
412+
| 2,638,999
413+
| 40.197
414+
| Intel `BID_UINT64`
415+
| 4,605,497
416+
| 70.150
417+
| Intel `BID_UINT128`
418+
| 13,075,436
419+
| 199.163
383420
|===
384421

385422
=== Division
@@ -412,13 +449,13 @@ Intel Compiler:
412449
| `decimal_fast128_t`
413450
| 8,105,004
414451
| 78.086
415-
| Intel `Decimal32`
452+
| Intel `BID_UINT32`
416453
| 1,561,213
417454
| 15.041
418-
| Intel `Decimal64`
455+
| Intel `BID_UINT64`
419456
| 3,115,862
420457
| 30.019
421-
| Intel `Decimal128`
458+
| Intel `BID_UINT128`
422459
| 7,474,712
423460
| 72.013
424461
|===
@@ -460,6 +497,15 @@ GCC:
460497
| GCC `_Decimal128`
461498
| 10,257,437
462499
| 130.490
500+
| Intel `BID_UINT32`
501+
| 3,242,695
502+
| 40.194
503+
| Intel `BID_UINT64`
504+
| 6,143,554
505+
| 76.151
506+
| Intel `BID_UINT128`
507+
| 13,499,022
508+
| 167.324
463509
|===
464510

465511
=== `from_chars`

test/benchmark_libbid.c

Lines changed: 55 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
#include <float.h>
1313
#include <fenv.h>
1414

15-
typedef uint32_t Decimal32;
16-
typedef uint64_t Decimal64;
15+
typedef BID_UINT32 Decimal32;
16+
typedef BID_UINT64 Decimal64;
1717
#include "../LIBRARY/src/bid_conf.h"
1818
#include "../LIBRARY/src/bid_functions.h"
1919
typedef BID_UINT128 Decimal128;
@@ -49,7 +49,7 @@ __attribute__ ((noinline)) void generate_vector_32(Decimal32* buffer, size_t buf
4949
{
5050
for (size_t i = 0; i < buffer_len; ++i)
5151
{
52-
buffer[i] = bid32_from_uint32(random_uint32(), BID_ROUNDING_DOWN, &flag);
52+
buffer[i] = bid32_from_uint32(random_uint32(), BID_ROUNDING_TO_NEAREST, &flag);
5353
}
5454
}
5555

@@ -86,7 +86,7 @@ __attribute__ ((noinline)) void generate_vector_64(Decimal64* buffer, size_t buf
8686
{
8787
for (size_t i = 0; i < buffer_len; ++i)
8888
{
89-
buffer[i] = bid64_from_uint64(random_uint64(), BID_ROUNDING_DOWN, &flag);
89+
buffer[i] = bid64_from_uint64(random_uint64(), BID_ROUNDING_TO_NEAREST, &flag);
9090
}
9191
}
9292

@@ -119,13 +119,51 @@ __attribute__ ((noinline)) void test_comparisons_64(Decimal64* data, const char*
119119
printf("Comparisons <%-10s >: %-10" PRIu64 " us (s=%zu)\n", label, elapsed_time_us, s);
120120
}
121121

122+
Decimal128 random_decimal128(void)
123+
{
124+
char str[64]; // Plenty of room for: -d.dddddddddddddddddddddddddddddddddE±eeee
125+
126+
// 1. Random sign (50/50)
127+
char sign = (random_uint64() & 1) ? '-' : '+';
128+
129+
// 2. Random 34-digit significand
130+
char digits[35];
131+
for (int i = 0; i < 34; i++)
132+
{
133+
digits[i] = '0' + (random_uint64() % 10);
134+
}
135+
136+
// Ensure first digit is non-zero (avoid leading zeros affecting value)
137+
if (digits[0] == '0')
138+
{
139+
digits[0] = '1' + (random_uint64() % 9);
140+
}
141+
digits[34] = '\0';
142+
143+
// 3. Random exponent: -6143 to +6144
144+
int exp_range = 6144 - (-6143) + 1; // 12288 possible values
145+
int exponent = (int)(random_uint64() % exp_range) - 6143;
146+
147+
// 4. Build string: "±D.DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDE±EEEE"
148+
snprintf(str, sizeof(str), "%c%c.%sE%+d",
149+
sign,
150+
digits[0], // integer part (1 digit)
151+
&digits[1], // fractional part (33 digits)
152+
exponent);
153+
154+
// 5. Parse to decimal128
155+
_IDEC_flags flags = 0;
156+
Decimal128 result = bid128_from_string(str, &flags);
157+
158+
return result;
159+
}
122160

123161
__attribute__ ((__noinline__)) void generate_vector_128(Decimal128* buffer, size_t buffer_len)
124162
{
125163
size_t i = 0;
126164
while (i < buffer_len)
127165
{
128-
buffer[i] = bid128_from_uint64(random_uint64());
166+
buffer[i] = random_decimal128();
129167
++i;
130168
}
131169
}
@@ -164,21 +202,21 @@ typedef Decimal32 (*operation_32)(Decimal32, Decimal32);
164202

165203
__attribute__ ((noinline)) Decimal32 add_32(Decimal32 a, Decimal32 b)
166204
{
167-
return bid32_add(a, b, BID_ROUNDING_DOWN, &flag);
205+
return bid32_add(a, b, BID_ROUNDING_TO_NEAREST, &flag);
168206
}
169207
__attribute__ ((noinline)) Decimal32 sub_32(Decimal32 a, Decimal32 b)
170208
{
171-
return bid32_sub(a, b, BID_ROUNDING_DOWN, &flag);
209+
return bid32_sub(a, b, BID_ROUNDING_TO_NEAREST, &flag);
172210
}
173211

174212
__attribute__ ((noinline)) Decimal32 mul_32(Decimal32 a, Decimal32 b)
175213
{
176-
return bid32_mul(a, b, BID_ROUNDING_DOWN, &flag);
214+
return bid32_mul(a, b, BID_ROUNDING_TO_NEAREST, &flag);
177215
}
178216

179217
__attribute__ ((noinline)) Decimal32 div_32(Decimal32 a, Decimal32 b)
180218
{
181-
return bid32_div(a, b, BID_ROUNDING_DOWN, &flag);
219+
return bid32_div(a, b, BID_ROUNDING_TO_NEAREST, &flag);
182220
}
183221

184222
__attribute__ ((noinline)) void test_two_element_operation_32(Decimal32* data, operation_32 op, const char* label, const char* op_label)
@@ -209,22 +247,22 @@ typedef Decimal64 (*operation_64)(Decimal64, Decimal64);
209247

210248
__attribute__ ((noinline)) Decimal64 add_64(Decimal64 a, Decimal64 b)
211249
{
212-
return bid64_add(a, b, BID_ROUNDING_DOWN, &flag);
250+
return bid64_add(a, b, BID_ROUNDING_TO_NEAREST, &flag);
213251
}
214252

215253
__attribute__ ((noinline)) Decimal64 sub_64(Decimal64 a, Decimal64 b)
216254
{
217-
return bid64_sub(a, b, BID_ROUNDING_DOWN, &flag);
255+
return bid64_sub(a, b, BID_ROUNDING_TO_NEAREST, &flag);
218256
}
219257

220258
__attribute__ ((noinline)) Decimal64 mul_64(Decimal64 a, Decimal64 b)
221259
{
222-
return bid64_mul(a, b, BID_ROUNDING_DOWN, &flag);
260+
return bid64_mul(a, b, BID_ROUNDING_TO_NEAREST, &flag);
223261
}
224262

225263
__attribute__ ((noinline)) Decimal64 div_64(Decimal64 a, Decimal64 b)
226264
{
227-
return bid64_div(a, b, BID_ROUNDING_DOWN, &flag);
265+
return bid64_div(a, b, BID_ROUNDING_TO_NEAREST, &flag);
228266
}
229267

230268
__attribute__ ((noinline)) void test_two_element_operation_64(Decimal64* data, operation_64 op, const char* label, const char* op_label)
@@ -256,22 +294,22 @@ typedef Decimal128 (*operation_128)(Decimal128, Decimal128);
256294

257295
__attribute__ ((__noinline__)) Decimal128 add_128(Decimal128 a, Decimal128 b)
258296
{
259-
return bid128_add(a, b, BID_ROUNDING_DOWN, &flag);
297+
return bid128_add(a, b, BID_ROUNDING_TO_NEAREST, &flag);
260298
}
261299

262300
__attribute__ ((__noinline__)) Decimal128 sub_128(Decimal128 a, Decimal128 b)
263301
{
264-
return bid128_sub(a, b, BID_ROUNDING_DOWN, &flag);
302+
return bid128_sub(a, b, BID_ROUNDING_TO_NEAREST, &flag);
265303
}
266304

267305
__attribute__ ((__noinline__)) Decimal128 mul_128(Decimal128 a, Decimal128 b)
268306
{
269-
return bid128_mul(a, b, BID_ROUNDING_DOWN, &flag);
307+
return bid128_mul(a, b, BID_ROUNDING_TO_NEAREST, &flag);
270308
}
271309

272310
__attribute__ ((__noinline__)) Decimal128 div_128(Decimal128 a, Decimal128 b)
273311
{
274-
return bid128_div(a, b, BID_ROUNDING_DOWN, &flag);
312+
return bid128_div(a, b, BID_ROUNDING_TO_NEAREST, &flag);
275313
}
276314

277315
__attribute__ ((__noinline__)) void test_two_element_operation_128(Decimal128* data, operation_128 op, const char* label, const char* op_label)

0 commit comments

Comments
 (0)