Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 61 additions & 15 deletions doc/modules/ROOT/pages/benchmarks.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ To run the GCC benchmarks you can use the following command: `gcc benchmark_libd

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].
You can the use the following command: `icx benchmark_libbid.c -O3 $PATH_TO_LIBBID/libbid.a -std=c17` followed by: `./a.out`
You can also use `gcc` instead of `icx`.

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

Expand Down Expand Up @@ -92,13 +93,13 @@ Intel Compiler:
| `decimal_fast128_t`
| 698,945
| 4.856
| Intel `Decimal32`
| Intel `BID_UINT32`
| 2,411,294
| 16.754
| Intel `Decimal64`
| Intel `BID_UINT64`
| 3,158,422
| 21.945
| Intel `Decimal128`
| Intel `BID_UINT128`
| 3,389,883
| 23.553
|===
Expand Down Expand Up @@ -140,6 +141,15 @@ GCC:
| GCC `_Decimal128`
| 914,600
| 14.844
| Intel `BID_UINT32`
| 3,718,385
| 60.348
| Intel `BID_UINT64`
| 5,721,887
| 92.865
| Intel `BID_UINT128`
| 7,090,648
| 115.080
|===

=== Addition
Expand Down Expand Up @@ -172,13 +182,13 @@ Intel Compiler:
| `decimal_fast128_t`
| 1,367,004
| 15.092
| Intel `Decimal32`
| Intel `BID_UINT32`
| 1,242,797
| 13.721
| Intel `Decimal64`
| Intel `BID_UINT64`
| 1,689,585
| 18.653
| Intel `Decimal128`
| Intel `BID_UINT128`
| 1,958,345
| 21.620
|===
Expand Down Expand Up @@ -220,6 +230,15 @@ GCC:
| GCC `_Decimal128`
| 3,368,864
| 46.138
| Intel `BID_UINT32`
| 2,838,194
| 38.879
| Intel `BID_UINT64`
| 3,297,652
| 45.163
| Intel `BID_UINT128`
| 2,796,283
| 38.296
|===

=== Subtraction
Expand Down Expand Up @@ -252,13 +271,13 @@ Intel Compiler:
| `decimal_fast128_t`
| 1,212,405
| 16.564
| Intel `Decimal32`
| Intel `BID_UINT32`
| 1,922,108
| 26.261
| Intel `Decimal64`
| Intel `BID_UINT64`
| 1,793,879
| 24.509
| Intel `Decimal128`
| Intel `BID_UINT128`
| 2,397,372
| 32.754
|===
Expand Down Expand Up @@ -300,6 +319,15 @@ GCC:
| GCC `_Decimal128`
| 3,178,891
| 10.816
| Intel `BID_UINT32`
| 3,762,566
| 12.802
| Intel `BID_UINT64`
| 3,432,814
| 11.680
| Intel `BID_UINT128`
| 3,725,534
| 12.676
|===

=== Multiplication
Expand Down Expand Up @@ -332,13 +360,13 @@ Intel Compiler:
| `decimal_fast128_t`
| 5,959,977
| 81.870
| Intel `Decimal32`
| Intel `BID_UINT32`
| 1,375,434
| 18.894
| Intel `Decimal64`
| Intel `BID_UINT64`
| 2,052,278
| 28.191
| Intel `Decimal128`
| Intel `BID_UINT128`
| 5,964,489
| 81.932
|===
Expand Down Expand Up @@ -380,6 +408,15 @@ GCC:
| GCC `_Decimal128`
| 7,050,299
| 107.289
| Intel `BID_UINT32`
| 2,638,999
| 40.197
| Intel `BID_UINT64`
| 4,605,497
| 70.150
| Intel `BID_UINT128`
| 13,075,436
| 199.163
|===

=== Division
Expand Down Expand Up @@ -412,13 +449,13 @@ Intel Compiler:
| `decimal_fast128_t`
| 8,105,004
| 78.086
| Intel `Decimal32`
| Intel `BID_UINT32`
| 1,561,213
| 15.041
| Intel `Decimal64`
| Intel `BID_UINT64`
| 3,115,862
| 30.019
| Intel `Decimal128`
| Intel `BID_UINT128`
| 7,474,712
| 72.013
|===
Expand Down Expand Up @@ -460,6 +497,15 @@ GCC:
| GCC `_Decimal128`
| 10,257,437
| 130.490
| Intel `BID_UINT32`
| 3,242,695
| 40.194
| Intel `BID_UINT64`
| 6,143,554
| 76.151
| Intel `BID_UINT128`
| 13,499,022
| 167.324
|===

=== `from_chars`
Expand Down
72 changes: 55 additions & 17 deletions test/benchmark_libbid.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
#include <float.h>
#include <fenv.h>

typedef uint32_t Decimal32;
typedef uint64_t Decimal64;
typedef BID_UINT32 Decimal32;
typedef BID_UINT64 Decimal64;
#include "../LIBRARY/src/bid_conf.h"
#include "../LIBRARY/src/bid_functions.h"
typedef BID_UINT128 Decimal128;
Expand Down Expand Up @@ -49,7 +49,7 @@ __attribute__ ((noinline)) void generate_vector_32(Decimal32* buffer, size_t buf
{
for (size_t i = 0; i < buffer_len; ++i)
{
buffer[i] = bid32_from_uint32(random_uint32(), BID_ROUNDING_DOWN, &flag);
buffer[i] = bid32_from_uint32(random_uint32(), BID_ROUNDING_TO_NEAREST, &flag);
}
}

Expand Down Expand Up @@ -86,7 +86,7 @@ __attribute__ ((noinline)) void generate_vector_64(Decimal64* buffer, size_t buf
{
for (size_t i = 0; i < buffer_len; ++i)
{
buffer[i] = bid64_from_uint64(random_uint64(), BID_ROUNDING_DOWN, &flag);
buffer[i] = bid64_from_uint64(random_uint64(), BID_ROUNDING_TO_NEAREST, &flag);
}
}

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

Decimal128 random_decimal128(void)
{
char str[64]; // Plenty of room for: -d.dddddddddddddddddddddddddddddddddE±eeee

// 1. Random sign (50/50)
char sign = (random_uint64() & 1) ? '-' : '+';

// 2. Random 34-digit significand
char digits[35];
for (int i = 0; i < 34; i++)
{
digits[i] = '0' + (random_uint64() % 10);
}

// Ensure first digit is non-zero (avoid leading zeros affecting value)
if (digits[0] == '0')
{
digits[0] = '1' + (random_uint64() % 9);
}
digits[34] = '\0';

// 3. Random exponent: -6143 to +6144
int exp_range = 6144 - (-6143) + 1; // 12288 possible values
int exponent = (int)(random_uint64() % exp_range) - 6143;

// 4. Build string: "±D.DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDE±EEEE"
snprintf(str, sizeof(str), "%c%c.%sE%+d",
sign,
digits[0], // integer part (1 digit)
&digits[1], // fractional part (33 digits)
exponent);

// 5. Parse to decimal128
_IDEC_flags flags = 0;
Decimal128 result = bid128_from_string(str, &flags);

return result;
}

__attribute__ ((__noinline__)) void generate_vector_128(Decimal128* buffer, size_t buffer_len)
{
size_t i = 0;
while (i < buffer_len)
{
buffer[i] = bid128_from_uint64(random_uint64());
buffer[i] = random_decimal128();
++i;
}
}
Expand Down Expand Up @@ -164,21 +202,21 @@ typedef Decimal32 (*operation_32)(Decimal32, Decimal32);

__attribute__ ((noinline)) Decimal32 add_32(Decimal32 a, Decimal32 b)
{
return bid32_add(a, b, BID_ROUNDING_DOWN, &flag);
return bid32_add(a, b, BID_ROUNDING_TO_NEAREST, &flag);
}
__attribute__ ((noinline)) Decimal32 sub_32(Decimal32 a, Decimal32 b)
{
return bid32_sub(a, b, BID_ROUNDING_DOWN, &flag);
return bid32_sub(a, b, BID_ROUNDING_TO_NEAREST, &flag);
}

__attribute__ ((noinline)) Decimal32 mul_32(Decimal32 a, Decimal32 b)
{
return bid32_mul(a, b, BID_ROUNDING_DOWN, &flag);
return bid32_mul(a, b, BID_ROUNDING_TO_NEAREST, &flag);
}

__attribute__ ((noinline)) Decimal32 div_32(Decimal32 a, Decimal32 b)
{
return bid32_div(a, b, BID_ROUNDING_DOWN, &flag);
return bid32_div(a, b, BID_ROUNDING_TO_NEAREST, &flag);
}

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

__attribute__ ((noinline)) Decimal64 add_64(Decimal64 a, Decimal64 b)
{
return bid64_add(a, b, BID_ROUNDING_DOWN, &flag);
return bid64_add(a, b, BID_ROUNDING_TO_NEAREST, &flag);
}

__attribute__ ((noinline)) Decimal64 sub_64(Decimal64 a, Decimal64 b)
{
return bid64_sub(a, b, BID_ROUNDING_DOWN, &flag);
return bid64_sub(a, b, BID_ROUNDING_TO_NEAREST, &flag);
}

__attribute__ ((noinline)) Decimal64 mul_64(Decimal64 a, Decimal64 b)
{
return bid64_mul(a, b, BID_ROUNDING_DOWN, &flag);
return bid64_mul(a, b, BID_ROUNDING_TO_NEAREST, &flag);
}

__attribute__ ((noinline)) Decimal64 div_64(Decimal64 a, Decimal64 b)
{
return bid64_div(a, b, BID_ROUNDING_DOWN, &flag);
return bid64_div(a, b, BID_ROUNDING_TO_NEAREST, &flag);
}

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

__attribute__ ((__noinline__)) Decimal128 add_128(Decimal128 a, Decimal128 b)
{
return bid128_add(a, b, BID_ROUNDING_DOWN, &flag);
return bid128_add(a, b, BID_ROUNDING_TO_NEAREST, &flag);
}

__attribute__ ((__noinline__)) Decimal128 sub_128(Decimal128 a, Decimal128 b)
{
return bid128_sub(a, b, BID_ROUNDING_DOWN, &flag);
return bid128_sub(a, b, BID_ROUNDING_TO_NEAREST, &flag);
}

__attribute__ ((__noinline__)) Decimal128 mul_128(Decimal128 a, Decimal128 b)
{
return bid128_mul(a, b, BID_ROUNDING_DOWN, &flag);
return bid128_mul(a, b, BID_ROUNDING_TO_NEAREST, &flag);
}

__attribute__ ((__noinline__)) Decimal128 div_128(Decimal128 a, Decimal128 b)
{
return bid128_div(a, b, BID_ROUNDING_DOWN, &flag);
return bid128_div(a, b, BID_ROUNDING_TO_NEAREST, &flag);
}

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