diff --git a/.gitignore b/.gitignore index edfa67a6..5dd63832 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,4 @@ *.app *.DS_Store +build/ diff --git a/doc/img/i128_graphs/linux/ARM32_benchmarks.png b/doc/img/i128_graphs/linux/ARM32_benchmarks.png new file mode 100644 index 00000000..dc6a7617 Binary files /dev/null and b/doc/img/i128_graphs/linux/ARM32_benchmarks.png differ diff --git a/doc/img/i128_graphs/linux/ARM32_relative_performance.png b/doc/img/i128_graphs/linux/ARM32_relative_performance.png new file mode 100644 index 00000000..83c8c583 Binary files /dev/null and b/doc/img/i128_graphs/linux/ARM32_relative_performance.png differ diff --git a/doc/img/i128_graphs/linux/ARM64_benchmarks.png b/doc/img/i128_graphs/linux/ARM64_benchmarks.png new file mode 100644 index 00000000..5fde4652 Binary files /dev/null and b/doc/img/i128_graphs/linux/ARM64_benchmarks.png differ diff --git a/doc/img/i128_graphs/linux/ARM64_relative_performance.png b/doc/img/i128_graphs/linux/ARM64_relative_performance.png new file mode 100644 index 00000000..ee4486b6 Binary files /dev/null and b/doc/img/i128_graphs/linux/ARM64_relative_performance.png differ diff --git a/doc/img/i128_graphs/linux/ppc64le_benchmarks.png b/doc/img/i128_graphs/linux/ppc64le_benchmarks.png new file mode 100644 index 00000000..fcda4936 Binary files /dev/null and b/doc/img/i128_graphs/linux/ppc64le_benchmarks.png differ diff --git a/doc/img/i128_graphs/linux/ppc64le_relative_performance.png b/doc/img/i128_graphs/linux/ppc64le_relative_performance.png new file mode 100644 index 00000000..d3882063 Binary files /dev/null and b/doc/img/i128_graphs/linux/ppc64le_relative_performance.png differ diff --git a/doc/img/i128_graphs/linux/s390x_benchmarks.png b/doc/img/i128_graphs/linux/s390x_benchmarks.png new file mode 100644 index 00000000..9884a44d Binary files /dev/null and b/doc/img/i128_graphs/linux/s390x_benchmarks.png differ diff --git a/doc/img/i128_graphs/linux/s390x_relative_performance.png b/doc/img/i128_graphs/linux/s390x_relative_performance.png new file mode 100644 index 00000000..4301edac Binary files /dev/null and b/doc/img/i128_graphs/linux/s390x_relative_performance.png differ diff --git a/doc/img/i128_graphs/linux/x64_benchmarks.png b/doc/img/i128_graphs/linux/x64_benchmarks.png new file mode 100644 index 00000000..a767b4fe Binary files /dev/null and b/doc/img/i128_graphs/linux/x64_benchmarks.png differ diff --git a/doc/img/i128_graphs/linux/x64_relative_performance.png b/doc/img/i128_graphs/linux/x64_relative_performance.png new file mode 100644 index 00000000..fff9bf7a Binary files /dev/null and b/doc/img/i128_graphs/linux/x64_relative_performance.png differ diff --git a/doc/img/i128_graphs/linux/x86_benchmarks.png b/doc/img/i128_graphs/linux/x86_benchmarks.png new file mode 100644 index 00000000..21d31774 Binary files /dev/null and b/doc/img/i128_graphs/linux/x86_benchmarks.png differ diff --git a/doc/img/i128_graphs/linux/x86_relative_performance.png b/doc/img/i128_graphs/linux/x86_relative_performance.png new file mode 100644 index 00000000..426e25e2 Binary files /dev/null and b/doc/img/i128_graphs/linux/x86_relative_performance.png differ diff --git a/doc/img/i128_graphs/macos/ARM64_benchmarks.png b/doc/img/i128_graphs/macos/ARM64_benchmarks.png new file mode 100644 index 00000000..8d7684cc Binary files /dev/null and b/doc/img/i128_graphs/macos/ARM64_benchmarks.png differ diff --git a/doc/img/i128_graphs/macos/ARM64_relative_performance.png b/doc/img/i128_graphs/macos/ARM64_relative_performance.png new file mode 100644 index 00000000..14b24670 Binary files /dev/null and b/doc/img/i128_graphs/macos/ARM64_relative_performance.png differ diff --git a/doc/img/i128_graphs/macos/x64_benchmarks.png b/doc/img/i128_graphs/macos/x64_benchmarks.png new file mode 100644 index 00000000..e377a803 Binary files /dev/null and b/doc/img/i128_graphs/macos/x64_benchmarks.png differ diff --git a/doc/img/i128_graphs/macos/x64_relative_performance.png b/doc/img/i128_graphs/macos/x64_relative_performance.png new file mode 100644 index 00000000..f33de2ca Binary files /dev/null and b/doc/img/i128_graphs/macos/x64_relative_performance.png differ diff --git a/doc/img/i128_graphs/windows/ARM64_benchmarks.png b/doc/img/i128_graphs/windows/ARM64_benchmarks.png new file mode 100644 index 00000000..136cbe9e Binary files /dev/null and b/doc/img/i128_graphs/windows/ARM64_benchmarks.png differ diff --git a/doc/img/i128_graphs/windows/ARM64_relative_performance.png b/doc/img/i128_graphs/windows/ARM64_relative_performance.png new file mode 100644 index 00000000..02fb8df2 Binary files /dev/null and b/doc/img/i128_graphs/windows/ARM64_relative_performance.png differ diff --git a/doc/img/i128_graphs/windows/x64_benchmarks.png b/doc/img/i128_graphs/windows/x64_benchmarks.png new file mode 100644 index 00000000..811ed34b Binary files /dev/null and b/doc/img/i128_graphs/windows/x64_benchmarks.png differ diff --git a/doc/img/i128_graphs/windows/x64_relative_performance.png b/doc/img/i128_graphs/windows/x64_relative_performance.png new file mode 100644 index 00000000..6d8d4b7b Binary files /dev/null and b/doc/img/i128_graphs/windows/x64_relative_performance.png differ diff --git a/doc/img/i128_graphs/windows/x86_benchmarks.png b/doc/img/i128_graphs/windows/x86_benchmarks.png new file mode 100644 index 00000000..1f259bf5 Binary files /dev/null and b/doc/img/i128_graphs/windows/x86_benchmarks.png differ diff --git a/doc/img/i128_graphs/windows/x86_relative_performance.png b/doc/img/i128_graphs/windows/x86_relative_performance.png new file mode 100644 index 00000000..777d531b Binary files /dev/null and b/doc/img/i128_graphs/windows/x86_relative_performance.png differ diff --git a/doc/u128_graphs/linux/ARM32_benchmarks.png b/doc/img/u128_graphs/linux/ARM32_benchmarks.png similarity index 100% rename from doc/u128_graphs/linux/ARM32_benchmarks.png rename to doc/img/u128_graphs/linux/ARM32_benchmarks.png diff --git a/doc/u128_graphs/linux/ARM32_relative_performance.png b/doc/img/u128_graphs/linux/ARM32_relative_performance.png similarity index 100% rename from doc/u128_graphs/linux/ARM32_relative_performance.png rename to doc/img/u128_graphs/linux/ARM32_relative_performance.png diff --git a/doc/u128_graphs/linux/ARM64_benchmarks.png b/doc/img/u128_graphs/linux/ARM64_benchmarks.png similarity index 100% rename from doc/u128_graphs/linux/ARM64_benchmarks.png rename to doc/img/u128_graphs/linux/ARM64_benchmarks.png diff --git a/doc/u128_graphs/linux/ARM64_relative_performance.png b/doc/img/u128_graphs/linux/ARM64_relative_performance.png similarity index 100% rename from doc/u128_graphs/linux/ARM64_relative_performance.png rename to doc/img/u128_graphs/linux/ARM64_relative_performance.png diff --git a/doc/u128_graphs/linux/ppc64le_benchmarks.png b/doc/img/u128_graphs/linux/ppc64le_benchmarks.png similarity index 100% rename from doc/u128_graphs/linux/ppc64le_benchmarks.png rename to doc/img/u128_graphs/linux/ppc64le_benchmarks.png diff --git a/doc/u128_graphs/linux/ppc64le_relative_performance.png b/doc/img/u128_graphs/linux/ppc64le_relative_performance.png similarity index 100% rename from doc/u128_graphs/linux/ppc64le_relative_performance.png rename to doc/img/u128_graphs/linux/ppc64le_relative_performance.png diff --git a/doc/u128_graphs/linux/s390x_benchmarks.png b/doc/img/u128_graphs/linux/s390x_benchmarks.png similarity index 100% rename from doc/u128_graphs/linux/s390x_benchmarks.png rename to doc/img/u128_graphs/linux/s390x_benchmarks.png diff --git a/doc/u128_graphs/linux/s390x_relative_performance.png b/doc/img/u128_graphs/linux/s390x_relative_performance.png similarity index 100% rename from doc/u128_graphs/linux/s390x_relative_performance.png rename to doc/img/u128_graphs/linux/s390x_relative_performance.png diff --git a/doc/u128_graphs/linux/x64_benchmarks.png b/doc/img/u128_graphs/linux/x64_benchmarks.png similarity index 100% rename from doc/u128_graphs/linux/x64_benchmarks.png rename to doc/img/u128_graphs/linux/x64_benchmarks.png diff --git a/doc/u128_graphs/linux/x64_relative_performance.png b/doc/img/u128_graphs/linux/x64_relative_performance.png similarity index 100% rename from doc/u128_graphs/linux/x64_relative_performance.png rename to doc/img/u128_graphs/linux/x64_relative_performance.png diff --git a/doc/u128_graphs/linux/x86_benchmarks.png b/doc/img/u128_graphs/linux/x86_benchmarks.png similarity index 100% rename from doc/u128_graphs/linux/x86_benchmarks.png rename to doc/img/u128_graphs/linux/x86_benchmarks.png diff --git a/doc/u128_graphs/linux/x86_relative_performance.png b/doc/img/u128_graphs/linux/x86_relative_performance.png similarity index 100% rename from doc/u128_graphs/linux/x86_relative_performance.png rename to doc/img/u128_graphs/linux/x86_relative_performance.png diff --git a/doc/u128_graphs/macos/ARM64_benchmarks.png b/doc/img/u128_graphs/macos/ARM64_benchmarks.png similarity index 100% rename from doc/u128_graphs/macos/ARM64_benchmarks.png rename to doc/img/u128_graphs/macos/ARM64_benchmarks.png diff --git a/doc/u128_graphs/macos/ARM64_relative_performance.png b/doc/img/u128_graphs/macos/ARM64_relative_performance.png similarity index 100% rename from doc/u128_graphs/macos/ARM64_relative_performance.png rename to doc/img/u128_graphs/macos/ARM64_relative_performance.png diff --git a/doc/u128_graphs/macos/x64_benchmarks.png b/doc/img/u128_graphs/macos/x64_benchmarks.png similarity index 100% rename from doc/u128_graphs/macos/x64_benchmarks.png rename to doc/img/u128_graphs/macos/x64_benchmarks.png diff --git a/doc/u128_graphs/macos/x64_relative_performance.png b/doc/img/u128_graphs/macos/x64_relative_performance.png similarity index 100% rename from doc/u128_graphs/macos/x64_relative_performance.png rename to doc/img/u128_graphs/macos/x64_relative_performance.png diff --git a/doc/u128_graphs/windows/arm64_benchmarks.png b/doc/img/u128_graphs/windows/arm64_benchmarks.png similarity index 100% rename from doc/u128_graphs/windows/arm64_benchmarks.png rename to doc/img/u128_graphs/windows/arm64_benchmarks.png diff --git a/doc/u128_graphs/windows/arm64_relative_performance.png b/doc/img/u128_graphs/windows/arm64_relative_performance.png similarity index 100% rename from doc/u128_graphs/windows/arm64_relative_performance.png rename to doc/img/u128_graphs/windows/arm64_relative_performance.png diff --git a/doc/u128_graphs/windows/x64_benchmarks.png b/doc/img/u128_graphs/windows/x64_benchmarks.png similarity index 100% rename from doc/u128_graphs/windows/x64_benchmarks.png rename to doc/img/u128_graphs/windows/x64_benchmarks.png diff --git a/doc/u128_graphs/windows/x64_relative_performance.png b/doc/img/u128_graphs/windows/x64_relative_performance.png similarity index 100% rename from doc/u128_graphs/windows/x64_relative_performance.png rename to doc/img/u128_graphs/windows/x64_relative_performance.png diff --git a/doc/u128_graphs/windows/x86_benchmarks.png b/doc/img/u128_graphs/windows/x86_benchmarks.png similarity index 100% rename from doc/u128_graphs/windows/x86_benchmarks.png rename to doc/img/u128_graphs/windows/x86_benchmarks.png diff --git a/doc/u128_graphs/windows/x86_relative_performance.png b/doc/img/u128_graphs/windows/x86_relative_performance.png similarity index 100% rename from doc/u128_graphs/windows/x86_relative_performance.png rename to doc/img/u128_graphs/windows/x86_relative_performance.png diff --git a/doc/int128.adoc b/doc/int128.adoc index 6fb83c3b..b86858ad 100644 --- a/doc/int128.adoc +++ b/doc/int128.adoc @@ -13,6 +13,7 @@ https://www.boost.org/LICENSE_1_0.txt :source-language: c++ :leveloffset: +1 +:imagesdir: ../img = Int128: Portable and Performant 128-bit integers Matt Borland @@ -39,6 +40,8 @@ include::int128/saturating.adoc[] include::int128/u128_benchmarks.adoc[] +include::int128/i128_benchmarks.adoc[] + include::int128/reference.adoc[] include::int128/copyright.adoc[] diff --git a/doc/int128/i128_benchmarks.adoc b/doc/int128/i128_benchmarks.adoc new file mode 100644 index 00000000..6335a77e --- /dev/null +++ b/doc/int128/i128_benchmarks.adoc @@ -0,0 +1,244 @@ +//// +Copyright 2025 Matt Borland +Distributed under the Boost Software License, Version 1.0. +https://www.boost.org/LICENSE_1_0.txt +//// + +[#i128_benchmarks] += `int128_t` Benchmarks +:idprefix: i128_benchmarks_ + +== Methodology + +The benchmarks below represent the time in microseconds it takes to perform 20'000'000 operations between two values of random width (e.g. 2x1 words, 1x2 words, etc.). +On most platforms we use the builtin `\__int128` as the reference benchmark. +When this is unavailable (such as on 32-bit architectures) we us `boost::multiprecision::int128_t` (abbreviated as `boost::mp::int128_t`) as it is widely used, and known to be portable. +On MSVC platforms we use as reference `std::_Signed128` from the header `<__msvc_int128.hpp>` since this is bundled with their compiler. + +== Linux + +=== x86_64 + +[cols="1,1,1,1"] +|=== +| Operation | `__int128` | `int128_t` | `boost::mp::int128_t` + +| Comparisons | 2086545 | 1807917 | 6119951 +| Addition | 229772 | 249644 | 620566 +| Subtraction | 245300 | 172252 | 1522422 +| Multiplication | 403481 | 246659 | 898345 +| Division | 4315016 | 4369512 | 4767180 +| Modulo | 4303454 | 4686920 | 4855786 +|=== + +//// +image::i128_graphs/linux/x64_benchmarks.png[x64 Benchmark Results, width=100%] +//// + +image::i128_graphs/linux/x64_relative_performance.png[x64 Relative Performance, width=100%] + +=== ARM64 + +[cols="1,1,1,1"] +|=== +| Operation | `__int128` | `int128_t` | `boost::mp::int128_t` + +| Comparisons | 3524205 | 2191692 | 5559916 +| Addition | 109691 | 126544 | 553814 +| Subtraction | 195129 | 196092 | 1024231 +| Multiplication | 286623 | 192214 | 924637 +| Division | 2350225 | 2163053 | 2718340 +| Modulo | 2345191 | 2167260 | 2380277 +|=== + +//// +image::i128_graphs/linux/ARM64_benchmarks.png[ARM64 Benchmark Results, width=100%] +//// + +image::i128_graphs/linux/ARM64_relative_performance.png[x64 Relative Performance, width=100%] + +=== S390x + +[cols="1,1,1,1"] +|=== +| Operation | `__int128` | `int128_t` | `boost::mp::int128_t` + +| Comparisons | 7033705 | 6231386 | 10322828 +| Addition | 558950 | 689575 | 1673032 +| Subtraction | 534362 | 329127 | 2149206 +| Multiplication | 911317 | 946090 | 1362947 +| Division | 4371582 | 3574992 | 3669927 +| Modulo | 4375939 | 3727994 | 4419901 +|=== + +//// +image::i128_graphs/linux/s390x_benchmarks.png[s390x Benchmark Results, width=100%] +//// + +image::i128_graphs/linux/s390x_relative_performance.png[s390x Relative Performance, width=100%] + +=== PPC64LE + +[cols="1,1,1,1"] +|=== +| Operation | `__int128` | `int128_t` | `boost::mp::int128_t` + +| Comparisons | 4538094 | 5796198 | 13907323 +| Addition | 221708 | 191841 | 1177034 +| Subtraction | 222629 | 174273 | 1861166 +| Multiplication | 193315 | 191785 | 878393 +| Division | 5607581 | 4669820 | 5616217 +| Modulo | 5623562 | 4750314 | 5641480 +|=== + +//// +image::i128_graphs/linux/ppc64le_benchmarks.png[ppc64le Benchmark Results, width=100%] +//// + +image::i128_graphs/linux/ppc64le_relative_performance.png[ppc64le Relative Performance, width=100%] + + +=== x86_32 + +NOTE: This platform has no hardware type so we compare relative to `boost::mp::int128_t` + +[cols="1,1,1"] +|=== +| Operation | `int128_t` | `boost::mp::int128_t` + +| Comparisons | 9530060 | 12168353 +| Addition | 785799 | 7777469 +| Subtraction | 778881 | 8214089 +| Multiplication | 1148024 | 9477355 +| Division | 10337258 | 22857709 +| Modulo | 10438037 | 14848256 +|=== + +//// +image::i128_graphs/linux/x86_benchmarks.png[x86 Benchmark Results, width=100%] +//// + +image::i128_graphs/linux/x86_relative_performance.png[x86 Relative Performance, width=100%] + +=== ARM32 + +NOTE: This platform has no hardware type so we compare relative to `boost::mp::int128_t` + +[cols="1,1,1"] +|=== +| Operation | `int128_t` | `boost::mp::int128_t` + +| Comparisons | 6149439 | 6432579 +| Addition | 457850 | 5669571 +| Subtraction | 488321 | 7464427 +| Multiplication | 1793874 | 11410321 +| Division | 17738614 | 38956122 +| Modulo | 18064819 | 30144743 +|=== + +//// +image::i128_graphs/linux/ARM32_benchmarks.png[ARM32 Benchmark Results, width=100%] +//// + +image::i128_graphs/linux/ARM32_relative_performance.png[ARM32 Relative Performance, width=100%] + +== Windows + +=== x86_64 + +[cols="1,1,1,1"] +|=== +| Operation | `std::_Signed128` | `int128_t` | `boost::mp::int128_t` + +| Comparisons | 2186843 | 2142626 | 4854983 +| Addition | 186771 | 184598 | 2645943 +| Subtraction | 193660 | 186335 | 2925784 +| Multiplication | 402806 | 117413 | 3887479 +| Division | 1612873 | 2369701 | 6437280 +| Modulo | 1637135 | 2218627 | 6236026 +|=== +//// +image::i128_graphs/windows/x64_benchmarks.png[x64 Benchmark Results, width=100%] +//// + +image::i128_graphs/windows/x64_relative_performance.png[x64 Relative Performance, width=100%] + +=== ARM64 + +[cols="1,1,1,1"] +|=== +| Operation | `std::_Signed128` | `int128_t` | `boost::mp::int128_t` + +| Comparisons | 911829 | 368104 | 2376802 +| Addition | 33233 | 34001 | 121700 +| Subtraction | 33411 | 34130 | 1488822 +| Multiplication | 117586 | 56324 | 1564799 +| Division | 1127267 | 1500725 | 2808293 +| Modulo | 1287100 | 1548073 | 2997474 +|=== +//// +image::i128_graphs/windows/ARM64_benchmarks.png[ARM64 Benchmark Results, width=100%] +//// + +image::i128_graphs/windows/ARM64_relative_performance.png[ARM64 Relative Performance, width=100%] + +=== x86_32 + +[cols="1,1,1,1"] +|=== +| Operation | `std::_Signed128` | `int128_t` | `boost::mp::int128_t` + +| Comparisons | 3187340 | 3046252 | 4269507 +| Addition | 185960 | 189165 | 2488618 +| Subtraction | 979025 | 192609 | 2783600 +| Multiplication | 1896082 | 3569921 | 4908622 +| Division | 5566403 | 4348306 | 6835035 +| Modulo | 4697289 | 4793845 | 6476032 +|=== +//// +image::i128_graphs/windows/x86_benchmarks.png[x86_32 Benchmark Results, width=100%] +//// + +image::i128_graphs/windows/x86_relative_performance.png[x86_32 Relative Performance, width=100%] + +== macOS + +=== ARM64 (Apple Silicon) + +[cols="1,1,1,1"] +|=== +| Operation | `__int128` | `int128_t` | `boost::mp::int128_t` + +| Comparisons | 134803 | 144313 | 338665 +| Addition | 20133 | 17820 | 168326 +| Subtraction | 20156 | 17864 | 169666 +| Multiplication | 19974 | 18572 | 77514 +| Division | 649380 | 666749 | 962183 +| Modulo | 708247 | 681991 | 1014055 +|=== + +//// +image::i128_graphs/macos/ARM64_benchmarks.png[ARM64 Benchmark Results, width=100%] +//// + +image::i128_graphs/macos/ARM64_relative_performance.png[ARM64 Relative Performance, width=100%] + +=== x86_64 + +[cols="1,1,1,1"] +|=== +| Operation | `__int128` | `int128_t` | `boost::mp::int128_t` + +| Comparisons | 1628142 | 1748005 | 4318109 +| Addition | 224648 | 180393 | 925013 +| Subtraction | 212849 | 131062 | 1876834 +| Multiplication | 432205 | 407829 | 651209 +| Division | 3924951 | 2409106 | 3719183 +| Modulo | 3042060 | 2423738 | 4443402 +|=== + +//// +image::i128_graphs/macos/x64_benchmarks.png[x64 Benchmark Results, width=100%] +//// + +image::i128_graphs/macos/x64_relative_performance.png[x64 Relative Performance, width=100%] diff --git a/doc/int128/overview.adoc b/doc/int128/overview.adoc index a49f3438..180dfac8 100644 --- a/doc/int128/overview.adoc +++ b/doc/int128/overview.adoc @@ -11,6 +11,7 @@ https://www.boost.org/LICENSE_1_0.txt == Description Boost.Int128 is a portable implementation of a signed, and an unsigned 128-bit integer and related functionality (e.g. bit counting). +Importantly, on all platforms, the `sizeof` the types provided in this library are 128-bits. The library is header-only, has no dependencies, and requires only C++14. @@ -26,7 +27,7 @@ Anywhere 128-bits are needed. == Supported Compilers Boost.Int128 is tested natively on Ubuntu (x86_64, s390x, and aarch64), macOS (x86_64, and Apple Silicon), and Windows (x32 and x64); -as well as emulated PPC64LE and STM32 using QEMU with the following compilers: +as well as emulated PPC64LE using QEMU with the following compilers: * GCC 5 and later * Clang 5 and later diff --git a/doc/int128/u128_benchmarks.adoc b/doc/int128/u128_benchmarks.adoc index 4acfc990..4534fd21 100644 --- a/doc/int128/u128_benchmarks.adoc +++ b/doc/int128/u128_benchmarks.adoc @@ -21,7 +21,7 @@ On MSVC platforms we use as reference `std::_Unsigned128` from the header `<__ms [cols="1,1,1,1"] |=== -| Operation | `std::_Unsigned128` | `uint128_t` | `boost::mp::uint128_t` +| Operation | `unsigned __int128` | `uint128_t` | `boost::mp::uint128_t` | Comparisons | 2068491 | 2416378 | 3191439 | Addition | 383258 | 180522 | 545521 @@ -41,7 +41,7 @@ image::u128_graphs/linux/x64_relative_performance.png[x64 Relative Performance, [cols="1,1,1,1"] |=== -| Operation | `std::_Unsigned128` | `uint128_t` | `boost::mp::uint128_t` +| Operation | `unsigned __int128` | `uint128_t` | `boost::mp::uint128_t` | Comparisons | 2068491 | 2416378 | 3191439 | Addition | 383258 | 180522 | 545521 @@ -61,7 +61,7 @@ image::u128_graphs/linux/ARM64_relative_performance.png[x64 Relative Performance [cols="1,1,1,1"] |=== -| Operation | `std::_Unsigned128` | `uint128_t` | `boost::mp::uint128_t` +| Operation | `unsigned __int128` | `uint128_t` | `boost::mp::uint128_t` | Comparisons | 14415854 | 12658246 | 16561079 | Addition | 1232397 | 1423451 | 2909066 @@ -81,7 +81,7 @@ image::u128_graphs/linux/s390x_relative_performance.png[s390x Relative Performan [cols="1,1,1,1"] |=== -| Operation | `std::_Unsigned128` | `uint128_t` | `boost::mp::uint128_t` +| Operation | `unsigned __int128` | `uint128_t` | `boost::mp::uint128_t` | Comparisons | 5242604 | 4450958 | 5704848 | Addition | 221776 | 193063 | 847504 @@ -144,6 +144,25 @@ image::u128_graphs/linux/ARM32_relative_performance.png[ARM32 Relative Performan == Windows +=== x86_64 + +[cols="1,1,1,1"] +|=== +| Operation | `std::_Unsigned128` | `uint128_t` | `boost::mp::uint128_t` + +| Comparisons | 2060556 | 1921174 | 3009890 +| Addition | 261475 | 106545 | 2710279 +| Subtraction | 178724 | 124181 | 3059187 +| Multiplication | 146063 | 136115 | 3495634 +| Division | 1332838 | 1360295 | 4852899 +| Modulo | 1465138 | 1471169 | 3926336 +|=== +//// +image::u128_graphs/windows/x64_benchmarks.png[x64 Benchmark Results, width=100%] +//// + +image::u128_graphs/windows/x64_relative_performance.png[x64 Relative Performance, width=100%] + === ARM64 [cols="1,1,1,1"] @@ -182,32 +201,13 @@ image::u128_graphs/windows/x86_benchmarks.png[x86_32 Benchmark Results, width=10 image::u128_graphs/windows/x86_relative_performance.png[x86_32 Relative Performance, width=100%] -=== x86_64 - -[cols="1,1,1,1"] -|=== -| Operation | `std::_Unsigned128` | `uint128_t` | `boost::mp::uint128_t` - -| Comparisons | 2060556 | 1921174 | 3009890 -| Addition | 261475 | 106545 | 2710279 -| Subtraction | 178724 | 124181 | 3059187 -| Multiplication | 146063 | 136115 | 3495634 -| Division | 1332838 | 1360295 | 4852899 -| Modulo | 1465138 | 1471169 | 3926336 -|=== -//// -image::u128_graphs/windows/x64_benchmarks.png[x64 Benchmark Results, width=100%] -//// - -image::u128_graphs/windows/x64_relative_performance.png[x64 Relative Performance, width=100%] - == macOS === ARM64 (Apple Silicon) [cols="1,1,1,1"] |=== -| Operation | `unsigned __in128` | `uint128_t` | `boost::mp::uint128_t` +| Operation | `unsigned __int128` | `uint128_t` | `boost::mp::uint128_t` | Comparisons | 131902 | 133564 | 134182 | Addition | 20613 | 17912 | 40176 @@ -227,7 +227,7 @@ image::u128_graphs/macos/ARM64_relative_performance.png[ARM64 Relative Performan [cols="1,1,1,1"] |=== -| Operation | `unsigned __in128` | `uint128_t` | `boost::mp::uint128_t` +| Operation | `unsigned __int128` | `uint128_t` | `boost::mp::uint128_t` | Comparisons | 131902 | 133564 | 134182 | Addition | 20613 | 17912 | 40176 diff --git a/doc/signed_plots.py b/doc/signed_plots.py new file mode 100644 index 00000000..9cac8d96 --- /dev/null +++ b/doc/signed_plots.py @@ -0,0 +1,220 @@ +import matplotlib.pyplot as plt +import numpy as np +import pandas as pd + +""" +# Linux x64 +data = { + 'Operation': ['Comparisons', 'Addition', 'Subtraction', 'Multiplication', 'Division', 'Modulo'], + '`__int128`': [2086545, 229772, 245300, 403481, 4315016, 4303454], + 'int128_t': [1807917, 249644, 172252, 246659, 4369512, 4686920], + 'boost::mp::int128_t': [6119951, 620566, 1522422, 898345, 4767180, 4855786] +} +""" + +""" +# Linux ARM64 +data = { + 'Operation': ['Comparisons', 'Addition', 'Subtraction', 'Multiplication', 'Division', 'Modulo'], + '`__int128`': [3524205, 109691, 195129, 286623, 2350225, 2345191], + 'int128_t': [2191692, 126544, 196092, 192214, 2163053, 2167260], + 'boost::mp::int128_t': [5559916, 553814, 1024231, 924637, 2718340, 2380277] +} +""" +""" +# Linux s390x +data = { + 'Operation': ['Comparisons', 'Addition', 'Subtraction', 'Multiplication', 'Division', 'Modulo'], + '`__int128`': [7033705, 558950, 534362, 911317, 4371582, 4375939], + 'int128_t': [6231386, 689575, 329127, 946090, 3574992, 3727994], + 'boost::mp::int128_t': [10322828, 1673032, 2149206, 1362947, 3669927, 4419901] +} +""" +""" +# Linux ppc64le +data = { + 'Operation': ['Comparisons', 'Addition', 'Subtraction', 'Multiplication', 'Division', 'Modulo'], + '`__int128`': [4538094, 221708, 222629, 193315, 5607581, 5623562], + 'int128_t': [5796198, 191841, 174273, 191785, 4669820, 4750314], + 'boost::mp::int128_t': [13907323, 1177034, 1861166, 878393, 5616217, 5641480] +} +""" +""" +# macos x64 +data = { + 'Operation': ['Comparisons', 'Addition', 'Subtraction', 'Multiplication', 'Division', 'Modulo'], + '`__int128`': [1628142, 224648, 212849, 432205, 3924951, 3042060], + 'int128_t': [1748005, 180393, 131062, 407829, 2409106, 2423738], + 'boost::mp::int128_t': [4318109, 925013, 1876834, 651209, 3719183, 4443402] +} +""" +""" +# macos ARM +data = { + 'Operation': ['Comparisons', 'Addition', 'Subtraction', 'Multiplication', 'Division', 'Modulo'], + '`__int128`': [134803, 20133, 20156, 19974, 649380, 708247], + 'int128_t': [144313, 17820, 17864, 18572, 666749, 681991], + 'boost::mp::int128_t': [338665, 168326, 169666, 77514, 962183, 1014055] +} +""" +""" +# MSVC 14.3 - ARM64 +data = { + 'Operation': ['Comparisons', 'Addition', 'Subtraction', 'Multiplication', 'Division', 'Modulo'], + 'std::_Signed128': [911829, 33233, 33411, 117586, 1127267, 1287100], + 'int128_t': [368104, 34001, 34130, 56324, 1500725, 1548073], + 'boost::mp::int128_t': [2376802, 121700, 1488822, 1564799, 2808293, 2997474] +} +""" +""" +# MSVC 14.3 - x64 +data = { + 'Operation': ['Comparisons', 'Addition', 'Subtraction', 'Multiplication', 'Division', 'Modulo'], + 'std::_Signed128': [2186843, 186771, 193660, 402806, 1612873, 1637135], + 'int128_t': [2142626, 184598, 186335, 117413, 2369701, 2218627], + 'boost::mp::int128_t': [4854983, 2645943, 2925784, 3887479, 6437280, 6236026] +} +""" + +# MSVC 14.3 - x86 +data = { + 'Operation': ['Comparisons', 'Addition', 'Subtraction', 'Multiplication', 'Division', 'Modulo'], + 'std::_Signed128': [3187340, 185960, 979025, 1896082, 5566403, 4697289], + 'int128_t': [3046252, 189165, 192609, 3569921, 4348306, 4793845], + 'boost::mp::int128_t': [4269507, 2488618, 2783600, 4908622, 6835035, 6476032] +} + +df = pd.DataFrame(data) + +# Function to determine color based on ranking +def get_colors_by_rank(row): + values = row[1:].values + ranks = np.argsort(values) + 1 + colors = [] + for rank in ranks: + if rank == 1: + colors.append('#90EE90') # Light Green - Best + elif rank == 2: + colors.append('#FFFFE0') # Light Yellow - Second + else: + colors.append('#FFB6C1') # Light Red - Third + return colors + +# Create figure with subplots +fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 10)) + +# Prepare data +operations = df['Operation'] +x = np.arange(len(operations)) +width = 0.25 + +# Get implementation names +implementations = df.columns[1:] + +# Plot 1: Regular scale bar chart with color coding +for i, (idx, row) in enumerate(df.iterrows()): + colors = get_colors_by_rank(row) + for j, impl in enumerate(implementations): + ax1.bar(x[i] + (j-1)*width, row[impl], width, + color=colors[j], edgecolor='black', linewidth=0.5, + label=impl if i == 0 else "") + +ax1.set_xlabel('Operations', fontsize=12) +ax1.set_ylabel('Time (nanoseconds)', fontsize=12) +ax1.set_title('MSVC 14.3 - x86_32 Benchmark Results', fontsize=14, fontweight='bold') +ax1.set_xticks(x) +ax1.set_xticklabels(operations, rotation=45, ha='right') +ax1.legend(loc='upper left') +ax1.grid(axis='y', alpha=0.3) + +# Add value labels on bars +for i, (idx, row) in enumerate(df.iterrows()): + for j, impl in enumerate(implementations): + ax1.text(x[i] + (j-1)*width, row[impl], f'{row[impl]:,}', + ha='center', va='bottom', fontsize=8, rotation=90) + +# Plot 2: Log scale for better visualization +for i, impl in enumerate(implementations): + bars = ax2.bar(x + (i-1)*width, df[impl], width, label=impl, edgecolor='black', linewidth=0.5) + + # Color each bar based on its rank within operation + for j, bar in enumerate(bars): + operation_values = df.iloc[j, 1:].values + rank = np.argsort(operation_values).tolist().index(i) + 1 + if rank == 1: + bar.set_facecolor('#90EE90') + elif rank == 2: + bar.set_facecolor('#FFFFE0') + else: + bar.set_facecolor('#FFB6C1') + +ax2.set_xlabel('Operations', fontsize=12) +ax2.set_ylabel('Time (nanoseconds) - Log Scale', fontsize=12) +ax2.set_title('MSVC 14.3 - x86_32 Benchmark Results (Log Scale)', fontsize=14, fontweight='bold') +ax2.set_yscale('log') +ax2.set_xticks(x) +ax2.set_xticklabels(operations, rotation=45, ha='right') +ax2.legend(loc='upper left') +ax2.grid(axis='y', alpha=0.3, which='both') + +plt.tight_layout() +plt.savefig('x86_benchmarks.png', dpi=300, bbox_inches='tight') +plt.show() + +# Create a normalized performance chart +fig3, ax3 = plt.subplots(figsize=(10, 6)) + +# Normalize data relative to __int128 +normalized_df = df.copy() +for col in implementations: + normalized_df[col] = df[col] / df['std::_Signed128'] + +# Plot normalized bars +for i, impl in enumerate(implementations): + if impl == 'std::_Signed128': + continue # Skip since it's always 1.0 + bars = ax3.bar(x + (i-1.5)*width, normalized_df[impl], width, + label=impl, edgecolor='black', linewidth=0.5) + + # Add value labels + for j, bar in enumerate(bars): + height = bar.get_height() + ax3.text(bar.get_x() + bar.get_width()/2., height, + f'{height:.2f}x', ha='center', va='bottom', fontsize=9) + +# Add reference line at 1.0 +ax3.axhline(y=1.0, color='red', linestyle='--', alpha=0.5, label='std::_Signed128 baseline') + +ax3.set_xlabel('Operations', fontsize=12) +ax3.set_ylabel('Relative Performance (vs __int128)', fontsize=12) +ax3.set_title('Relative Performance Comparison - x86_32', fontsize=14, fontweight='bold') +ax3.set_xticks(x) +ax3.set_xticklabels(operations, rotation=45, ha='right') +ax3.legend() +ax3.grid(axis='y', alpha=0.3) + +# Add interpretation text +ax3.text(0.02, 0.98, 'Lower is better', transform=ax3.transAxes, + fontsize=10, verticalalignment='top', style='italic') + +plt.tight_layout() +plt.savefig('x86_relative_performance.png', dpi=300, bbox_inches='tight') +plt.show() + +# Generate summary statistics +print("\nPerformance Summary (x64):") +print("-" * 50) +for impl in implementations: + if impl == '__int128': + continue + avg_ratio = normalized_df[impl].mean() + print(f"{impl}: {avg_ratio:.2f}x average vs __int128") + +print("\nBest performer by operation:") +print("-" * 50) +for i, op in enumerate(operations): + row_data = df.iloc[i, 1:] + best_impl = row_data.idxmin() + best_time = row_data.min() + print(f"{op}: {best_impl} ({best_time:,} ns)") + diff --git a/doc/signed_plots_32bit.py b/doc/signed_plots_32bit.py new file mode 100644 index 00000000..73dbbdd2 --- /dev/null +++ b/doc/signed_plots_32bit.py @@ -0,0 +1,154 @@ +import matplotlib.pyplot as plt +import numpy as np +import pandas as pd + +""" +# Linux x86_32 +data = { + 'Operation': ['Comparisons', 'Addition', 'Subtraction', 'Multiplication', 'Division', 'Modulo'], + 'int128_t': [9530060, 785799, 778881, 1148024, 10337258, 10438037], + 'boost::mp::int128_t': [12168353, 7777469, 8214089, 9477355, 22857709, 14848256] +} +""" + +# Linux ARM32 +data = { + 'Operation': ['Comparisons', 'Addition', 'Subtraction', 'Multiplication', 'Division', 'Modulo'], + 'int128_t': [6149439, 457850, 488321, 1793874, 17738614, 18064819], + 'boost::mp::int128_t': [6432579, 5669571, 7464427, 11410321, 38956122, 30144743] +} + +df = pd.DataFrame(data) + +# Function to determine color based on ranking +def get_colors_by_rank(row): + values = row[1:].values + ranks = np.argsort(values) + 1 + colors = [] + for rank in ranks: + if rank == 1: + colors.append('#90EE90') # Light Green - Best + elif rank == 2: + colors.append('#FFFFE0') # Light Yellow - Second + else: + colors.append('#FFB6C1') # Light Red - Third + return colors + +# Create figure with subplots +fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 10)) + +# Prepare data +operations = df['Operation'] +x = np.arange(len(operations)) +width = 0.25 + +# Get implementation names +implementations = df.columns[1:] + +# Plot 1: Regular scale bar chart with color coding +for i, (idx, row) in enumerate(df.iterrows()): + colors = get_colors_by_rank(row) + for j, impl in enumerate(implementations): + ax1.bar(x[i] + (j-1)*width, row[impl], width, + color=colors[j], edgecolor='black', linewidth=0.5, + label=impl if i == 0 else "") + +ax1.set_xlabel('Operations', fontsize=12) +ax1.set_ylabel('Time (nanoseconds)', fontsize=12) +ax1.set_title('GCC 14 - ARM32 Benchmark Results', fontsize=14, fontweight='bold') +ax1.set_xticks(x) +ax1.set_xticklabels(operations, rotation=45, ha='right') +ax1.legend(loc='upper left') +ax1.grid(axis='y', alpha=0.3) + +# Add value labels on bars +for i, (idx, row) in enumerate(df.iterrows()): + for j, impl in enumerate(implementations): + ax1.text(x[i] + (j-1)*width, row[impl], f'{row[impl]:,}', + ha='center', va='bottom', fontsize=8, rotation=90) + +# Plot 2: Log scale for better visualization +for i, impl in enumerate(implementations): + bars = ax2.bar(x + (i-1)*width, df[impl], width, label=impl, edgecolor='black', linewidth=0.5) + + # Color each bar based on its rank within operation + for j, bar in enumerate(bars): + operation_values = df.iloc[j, 1:].values + rank = np.argsort(operation_values).tolist().index(i) + 1 + if rank == 1: + bar.set_facecolor('#90EE90') + elif rank == 2: + bar.set_facecolor('#FFFFE0') + else: + bar.set_facecolor('#FFB6C1') + +ax2.set_xlabel('Operations', fontsize=12) +ax2.set_ylabel('Time (nanoseconds) - Log Scale', fontsize=12) +ax2.set_title('GCC 14 - ARM32 Benchmark Results (Log Scale)', fontsize=14, fontweight='bold') +ax2.set_yscale('log') +ax2.set_xticks(x) +ax2.set_xticklabels(operations, rotation=45, ha='right') +ax2.legend(loc='upper left') +ax2.grid(axis='y', alpha=0.3, which='both') + +plt.tight_layout() +plt.savefig('ARM32_benchmarks.png', dpi=300, bbox_inches='tight') +plt.show() + +# Create a normalized performance chart +fig3, ax3 = plt.subplots(figsize=(10, 6)) + +# Normalize data relative to boost::mp::int128_t +normalized_df = df.copy() +for col in implementations: + normalized_df[col] = df[col] / df['boost::mp::int128_t'] + +# Plot normalized bars +for i, impl in enumerate(implementations): + if impl == 'boost::mp::int128_t': + continue # Skip since it's always 1.0 + bars = ax3.bar(x + (i-1.5)*width, normalized_df[impl], width, + label=impl, edgecolor='black', linewidth=0.5) + + # Add value labels + for j, bar in enumerate(bars): + height = bar.get_height() + ax3.text(bar.get_x() + bar.get_width()/2., height, + f'{height:.2f}x', ha='center', va='bottom', fontsize=9) + +# Add reference line at 1.0 +ax3.axhline(y=1.0, color='red', linestyle='--', alpha=0.5, label='boost::mp::int128_t baseline') + +ax3.set_xlabel('Operations', fontsize=12) +ax3.set_ylabel('Relative Performance (vs boost::mp::int128_t)', fontsize=12) +ax3.set_title('Relative Performance Comparison - ARM32', fontsize=14, fontweight='bold') +ax3.set_xticks(x) +ax3.set_xticklabels(operations, rotation=45, ha='right') +ax3.legend() +ax3.grid(axis='y', alpha=0.3) + +# Add interpretation text +ax3.text(0.02, 0.98, 'Lower is better', transform=ax3.transAxes, + fontsize=10, verticalalignment='top', style='italic') + +plt.tight_layout() +plt.savefig('ARM32_relative_performance.png', dpi=300, bbox_inches='tight') +plt.show() + +# Generate summary statistics +print("\nPerformance Summary (x64):") +print("-" * 50) +for impl in implementations: + if impl == '__int128': + continue + avg_ratio = normalized_df[impl].mean() + print(f"{impl}: {avg_ratio:.2f}x average vs __int128") + +print("\nBest performer by operation:") +print("-" * 50) +for i, op in enumerate(operations): + row_data = df.iloc[i, 1:] + best_impl = row_data.idxmin() + best_time = row_data.min() + print(f"{op}: {best_impl} ({best_time:,} ns)") +