22 #include "benchmark/benchmark.h" 27 constexpr
size_t kSampleSize = 1000000;
29 std::mt19937 MakeRandomEngine() {
31 std::seed_seq seed({r(), r(), r(), r(), r(), r(), r(), r()});
32 return std::mt19937(seed);
35 std::vector<std::pair<absl::uint128, absl::uint128>>
36 GetRandomClass128SampleUniformDivisor() {
37 std::vector<std::pair<absl::uint128, absl::uint128>> values;
38 std::mt19937 random = MakeRandomEngine();
39 std::uniform_int_distribution<uint64_t> uniform_uint64;
40 values.reserve(kSampleSize);
41 for (
size_t i = 0;
i < kSampleSize; ++
i) {
46 values.emplace_back(std::max(a, b),
52 void BM_DivideClass128UniformDivisor(benchmark::State& state) {
53 auto values = GetRandomClass128SampleUniformDivisor();
54 while (state.KeepRunningBatch(values.size())) {
55 for (
const auto&
pair : values) {
56 benchmark::DoNotOptimize(
pair.first /
pair.second);
60 BENCHMARK(BM_DivideClass128UniformDivisor);
62 std::vector<std::pair<absl::uint128, uint64_t>>
63 GetRandomClass128SampleSmallDivisor() {
64 std::vector<std::pair<absl::uint128, uint64_t>> values;
65 std::mt19937 random = MakeRandomEngine();
66 std::uniform_int_distribution<uint64_t> uniform_uint64;
67 values.reserve(kSampleSize);
68 for (
size_t i = 0;
i < kSampleSize; ++
i) {
71 uint64_t b = std::max(uint64_t{2}, uniform_uint64(random));
77 void BM_DivideClass128SmallDivisor(benchmark::State& state) {
78 auto values = GetRandomClass128SampleSmallDivisor();
79 while (state.KeepRunningBatch(values.size())) {
80 for (
const auto&
pair : values) {
81 benchmark::DoNotOptimize(
pair.first /
pair.second);
85 BENCHMARK(BM_DivideClass128SmallDivisor);
87 std::vector<std::pair<absl::uint128, absl::uint128>> GetRandomClass128Sample() {
88 std::vector<std::pair<absl::uint128, absl::uint128>> values;
89 std::mt19937 random = MakeRandomEngine();
90 std::uniform_int_distribution<uint64_t> uniform_uint64;
91 values.reserve(kSampleSize);
92 for (
size_t i = 0;
i < kSampleSize; ++
i) {
100 void BM_MultiplyClass128(benchmark::State& state) {
101 auto values = GetRandomClass128Sample();
102 while (state.KeepRunningBatch(values.size())) {
103 for (
const auto&
pair : values) {
104 benchmark::DoNotOptimize(
pair.first *
pair.second);
108 BENCHMARK(BM_MultiplyClass128);
110 void BM_AddClass128(benchmark::State& state) {
111 auto values = GetRandomClass128Sample();
112 while (state.KeepRunningBatch(values.size())) {
113 for (
const auto&
pair : values) {
114 benchmark::DoNotOptimize(
pair.first +
pair.second);
118 BENCHMARK(BM_AddClass128);
120 #ifdef ABSL_HAVE_INTRINSIC_INT128 124 class UniformIntDistribution128 {
127 unsigned __int128 operator()(std::mt19937& generator) {
128 return (static_cast<unsigned __int128>(dist64_(generator)) << 64) |
133 std::uniform_int_distribution<uint64_t> dist64_;
136 std::vector<std::pair<unsigned __int128, unsigned __int128>>
137 GetRandomIntrinsic128SampleUniformDivisor() {
138 std::vector<std::pair<unsigned __int128, unsigned __int128>> values;
139 std::mt19937 random = MakeRandomEngine();
140 UniformIntDistribution128 uniform_uint128;
141 values.reserve(kSampleSize);
142 for (
size_t i = 0;
i < kSampleSize; ++
i) {
143 unsigned __int128 a = uniform_uint128(random);
144 unsigned __int128 b = uniform_uint128(random);
147 std::max(static_cast<unsigned __int128>(2), std::min(a, b)));
152 void BM_DivideIntrinsic128UniformDivisor(benchmark::State& state) {
153 auto values = GetRandomIntrinsic128SampleUniformDivisor();
154 while (state.KeepRunningBatch(values.size())) {
155 for (
const auto&
pair : values) {
156 benchmark::DoNotOptimize(
pair.first /
pair.second);
160 BENCHMARK(BM_DivideIntrinsic128UniformDivisor);
162 std::vector<std::pair<unsigned __int128, uint64_t>>
163 GetRandomIntrinsic128SampleSmallDivisor() {
164 std::vector<std::pair<unsigned __int128, uint64_t>> values;
165 std::mt19937 random = MakeRandomEngine();
166 UniformIntDistribution128 uniform_uint128;
167 std::uniform_int_distribution<uint64_t> uniform_uint64;
168 values.reserve(kSampleSize);
169 for (
size_t i = 0;
i < kSampleSize; ++
i) {
170 unsigned __int128 a = uniform_uint128(random);
171 uint64_t b = std::max(uint64_t{2}, uniform_uint64(random));
172 values.emplace_back(std::max(a, static_cast<unsigned __int128>(b)), b);
177 void BM_DivideIntrinsic128SmallDivisor(benchmark::State& state) {
178 auto values = GetRandomIntrinsic128SampleSmallDivisor();
179 while (state.KeepRunningBatch(values.size())) {
180 for (
const auto&
pair : values) {
181 benchmark::DoNotOptimize(
pair.first /
pair.second);
185 BENCHMARK(BM_DivideIntrinsic128SmallDivisor);
187 std::vector<std::pair<unsigned __int128, unsigned __int128>>
188 GetRandomIntrinsic128Sample() {
189 std::vector<std::pair<unsigned __int128, unsigned __int128>> values;
190 std::mt19937 random = MakeRandomEngine();
191 UniformIntDistribution128 uniform_uint128;
192 values.reserve(kSampleSize);
193 for (
size_t i = 0;
i < kSampleSize; ++
i) {
194 values.emplace_back(uniform_uint128(random), uniform_uint128(random));
199 void BM_MultiplyIntrinsic128(benchmark::State& state) {
200 auto values = GetRandomIntrinsic128Sample();
201 while (state.KeepRunningBatch(values.size())) {
202 for (
const auto&
pair : values) {
203 benchmark::DoNotOptimize(
pair.first *
pair.second);
207 BENCHMARK(BM_MultiplyIntrinsic128);
209 void BM_AddIntrinsic128(benchmark::State& state) {
210 auto values = GetRandomIntrinsic128Sample();
211 while (state.KeepRunningBatch(values.size())) {
212 for (
const auto&
pair : values) {
213 benchmark::DoNotOptimize(
pair.first +
pair.second);
217 BENCHMARK(BM_AddIntrinsic128);
219 #endif // ABSL_HAVE_INTRINSIC_INT128
std::pair< std::string, std::string > pair
constexpr uint128 MakeUint128(uint64_t high, uint64_t low)