diff --git a/doc/modules/ROOT/pages/benchmarks.adoc b/doc/modules/ROOT/pages/benchmarks.adoc index 593a3bce8..bea3f4617 100644 --- a/doc/modules/ROOT/pages/benchmarks.adoc +++ b/doc/modules/ROOT/pages/benchmarks.adoc @@ -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 @@ -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 |=== @@ -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 @@ -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 |=== @@ -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 @@ -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 |=== @@ -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 @@ -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 |=== @@ -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 @@ -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 |=== @@ -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` diff --git a/test/benchmark_libbid.c b/test/benchmark_libbid.c index 725a24e3c..5a1b15273 100644 --- a/test/benchmark_libbid.c +++ b/test/benchmark_libbid.c @@ -12,8 +12,8 @@ #include #include -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; @@ -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); } } @@ -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); } } @@ -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; } } @@ -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) @@ -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) @@ -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)