int128_benchmark.cc
Go to the documentation of this file.
00001 // Copyright 2017 The Abseil Authors.
00002 //
00003 // Licensed under the Apache License, Version 2.0 (the "License");
00004 // you may not use this file except in compliance with the License.
00005 // You may obtain a copy of the License at
00006 //
00007 //      https://www.apache.org/licenses/LICENSE-2.0
00008 //
00009 // Unless required by applicable law or agreed to in writing, software
00010 // distributed under the License is distributed on an "AS IS" BASIS,
00011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00012 // See the License for the specific language governing permissions and
00013 // limitations under the License.
00014 
00015 #include "absl/numeric/int128.h"
00016 
00017 #include <algorithm>
00018 #include <cstdint>
00019 #include <random>
00020 #include <vector>
00021 
00022 #include "benchmark/benchmark.h"
00023 #include "absl/base/config.h"
00024 
00025 namespace {
00026 
00027 constexpr size_t kSampleSize = 1000000;
00028 
00029 std::mt19937 MakeRandomEngine() {
00030   std::random_device r;
00031   std::seed_seq seed({r(), r(), r(), r(), r(), r(), r(), r()});
00032   return std::mt19937(seed);
00033 }
00034 
00035 std::vector<std::pair<absl::uint128, absl::uint128>>
00036 GetRandomClass128SampleUniformDivisor() {
00037   std::vector<std::pair<absl::uint128, absl::uint128>> values;
00038   std::mt19937 random = MakeRandomEngine();
00039   std::uniform_int_distribution<uint64_t> uniform_uint64;
00040   values.reserve(kSampleSize);
00041   for (size_t i = 0; i < kSampleSize; ++i) {
00042     absl::uint128 a =
00043         absl::MakeUint128(uniform_uint64(random), uniform_uint64(random));
00044     absl::uint128 b =
00045         absl::MakeUint128(uniform_uint64(random), uniform_uint64(random));
00046     values.emplace_back(std::max(a, b),
00047                         std::max(absl::uint128(2), std::min(a, b)));
00048   }
00049   return values;
00050 }
00051 
00052 void BM_DivideClass128UniformDivisor(benchmark::State& state) {
00053   auto values = GetRandomClass128SampleUniformDivisor();
00054   while (state.KeepRunningBatch(values.size())) {
00055     for (const auto& pair : values) {
00056       benchmark::DoNotOptimize(pair.first / pair.second);
00057     }
00058   }
00059 }
00060 BENCHMARK(BM_DivideClass128UniformDivisor);
00061 
00062 std::vector<std::pair<absl::uint128, uint64_t>>
00063 GetRandomClass128SampleSmallDivisor() {
00064   std::vector<std::pair<absl::uint128, uint64_t>> values;
00065   std::mt19937 random = MakeRandomEngine();
00066   std::uniform_int_distribution<uint64_t> uniform_uint64;
00067   values.reserve(kSampleSize);
00068   for (size_t i = 0; i < kSampleSize; ++i) {
00069     absl::uint128 a =
00070         absl::MakeUint128(uniform_uint64(random), uniform_uint64(random));
00071     uint64_t b = std::max(uint64_t{2}, uniform_uint64(random));
00072     values.emplace_back(std::max(a, absl::uint128(b)), b);
00073   }
00074   return values;
00075 }
00076 
00077 void BM_DivideClass128SmallDivisor(benchmark::State& state) {
00078   auto values = GetRandomClass128SampleSmallDivisor();
00079   while (state.KeepRunningBatch(values.size())) {
00080     for (const auto& pair : values) {
00081       benchmark::DoNotOptimize(pair.first / pair.second);
00082     }
00083   }
00084 }
00085 BENCHMARK(BM_DivideClass128SmallDivisor);
00086 
00087 std::vector<std::pair<absl::uint128, absl::uint128>> GetRandomClass128Sample() {
00088   std::vector<std::pair<absl::uint128, absl::uint128>> values;
00089   std::mt19937 random = MakeRandomEngine();
00090   std::uniform_int_distribution<uint64_t> uniform_uint64;
00091   values.reserve(kSampleSize);
00092   for (size_t i = 0; i < kSampleSize; ++i) {
00093     values.emplace_back(
00094         absl::MakeUint128(uniform_uint64(random), uniform_uint64(random)),
00095         absl::MakeUint128(uniform_uint64(random), uniform_uint64(random)));
00096   }
00097   return values;
00098 }
00099 
00100 void BM_MultiplyClass128(benchmark::State& state) {
00101   auto values = GetRandomClass128Sample();
00102   while (state.KeepRunningBatch(values.size())) {
00103     for (const auto& pair : values) {
00104       benchmark::DoNotOptimize(pair.first * pair.second);
00105     }
00106   }
00107 }
00108 BENCHMARK(BM_MultiplyClass128);
00109 
00110 void BM_AddClass128(benchmark::State& state) {
00111   auto values = GetRandomClass128Sample();
00112   while (state.KeepRunningBatch(values.size())) {
00113     for (const auto& pair : values) {
00114       benchmark::DoNotOptimize(pair.first + pair.second);
00115     }
00116   }
00117 }
00118 BENCHMARK(BM_AddClass128);
00119 
00120 #ifdef ABSL_HAVE_INTRINSIC_INT128
00121 
00122 // Some implementations of <random> do not support __int128 when it is
00123 // available, so we make our own uniform_int_distribution-like type.
00124 class UniformIntDistribution128 {
00125  public:
00126   // NOLINTNEXTLINE: mimicking std::uniform_int_distribution API
00127   unsigned __int128 operator()(std::mt19937& generator) {
00128     return (static_cast<unsigned __int128>(dist64_(generator)) << 64) |
00129            dist64_(generator);
00130   }
00131 
00132  private:
00133   std::uniform_int_distribution<uint64_t> dist64_;
00134 };
00135 
00136 std::vector<std::pair<unsigned __int128, unsigned __int128>>
00137 GetRandomIntrinsic128SampleUniformDivisor() {
00138   std::vector<std::pair<unsigned __int128, unsigned __int128>> values;
00139   std::mt19937 random = MakeRandomEngine();
00140   UniformIntDistribution128 uniform_uint128;
00141   values.reserve(kSampleSize);
00142   for (size_t i = 0; i < kSampleSize; ++i) {
00143     unsigned __int128 a = uniform_uint128(random);
00144     unsigned __int128 b = uniform_uint128(random);
00145     values.emplace_back(
00146         std::max(a, b),
00147         std::max(static_cast<unsigned __int128>(2), std::min(a, b)));
00148   }
00149   return values;
00150 }
00151 
00152 void BM_DivideIntrinsic128UniformDivisor(benchmark::State& state) {
00153   auto values = GetRandomIntrinsic128SampleUniformDivisor();
00154   while (state.KeepRunningBatch(values.size())) {
00155     for (const auto& pair : values) {
00156       benchmark::DoNotOptimize(pair.first / pair.second);
00157     }
00158   }
00159 }
00160 BENCHMARK(BM_DivideIntrinsic128UniformDivisor);
00161 
00162 std::vector<std::pair<unsigned __int128, uint64_t>>
00163 GetRandomIntrinsic128SampleSmallDivisor() {
00164   std::vector<std::pair<unsigned __int128, uint64_t>> values;
00165   std::mt19937 random = MakeRandomEngine();
00166   UniformIntDistribution128 uniform_uint128;
00167   std::uniform_int_distribution<uint64_t> uniform_uint64;
00168   values.reserve(kSampleSize);
00169   for (size_t i = 0; i < kSampleSize; ++i) {
00170     unsigned __int128 a = uniform_uint128(random);
00171     uint64_t b = std::max(uint64_t{2}, uniform_uint64(random));
00172     values.emplace_back(std::max(a, static_cast<unsigned __int128>(b)), b);
00173   }
00174   return values;
00175 }
00176 
00177 void BM_DivideIntrinsic128SmallDivisor(benchmark::State& state) {
00178   auto values = GetRandomIntrinsic128SampleSmallDivisor();
00179   while (state.KeepRunningBatch(values.size())) {
00180     for (const auto& pair : values) {
00181       benchmark::DoNotOptimize(pair.first / pair.second);
00182     }
00183   }
00184 }
00185 BENCHMARK(BM_DivideIntrinsic128SmallDivisor);
00186 
00187 std::vector<std::pair<unsigned __int128, unsigned __int128>>
00188       GetRandomIntrinsic128Sample() {
00189   std::vector<std::pair<unsigned __int128, unsigned __int128>> values;
00190   std::mt19937 random = MakeRandomEngine();
00191   UniformIntDistribution128 uniform_uint128;
00192   values.reserve(kSampleSize);
00193   for (size_t i = 0; i < kSampleSize; ++i) {
00194     values.emplace_back(uniform_uint128(random), uniform_uint128(random));
00195   }
00196   return values;
00197 }
00198 
00199 void BM_MultiplyIntrinsic128(benchmark::State& state) {
00200   auto values = GetRandomIntrinsic128Sample();
00201   while (state.KeepRunningBatch(values.size())) {
00202     for (const auto& pair : values) {
00203       benchmark::DoNotOptimize(pair.first * pair.second);
00204     }
00205   }
00206 }
00207 BENCHMARK(BM_MultiplyIntrinsic128);
00208 
00209 void BM_AddIntrinsic128(benchmark::State& state) {
00210   auto values = GetRandomIntrinsic128Sample();
00211   while (state.KeepRunningBatch(values.size())) {
00212     for (const auto& pair : values) {
00213       benchmark::DoNotOptimize(pair.first + pair.second);
00214     }
00215   }
00216 }
00217 BENCHMARK(BM_AddIntrinsic128);
00218 
00219 #endif  // ABSL_HAVE_INTRINSIC_INT128
00220 
00221 }  // namespace


abseil_cpp
Author(s):
autogenerated on Wed Jun 19 2019 19:42:15