ParallelBenchmark.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. /*
  2. * Copyright 2014-present Facebook, Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include <array>
  17. #include <future>
  18. #include <iostream>
  19. #include <vector>
  20. #include <glog/logging.h>
  21. #include <folly/gen/Base.h>
  22. #include <folly/gen/Parallel.h>
  23. #include <folly/gen/test/Bench.h>
  24. DEFINE_int32(
  25. threads,
  26. std::max(1, (int32_t)sysconf(_SC_NPROCESSORS_CONF) / 2),
  27. "Num threads.");
  28. using namespace folly::gen;
  29. using std::vector;
  30. constexpr int kFib = 28; // unit of work
  31. size_t fib(int n) {
  32. return n <= 1 ? 1 : fib(n - 1) + fib(n - 2);
  33. }
  34. static auto isPrimeSlow = [](int n) {
  35. if (n < 2) {
  36. return false;
  37. } else if (n > 2) {
  38. for (int d = 3; d * d <= n; d += 2) {
  39. if (0 == n % d) {
  40. return false;
  41. }
  42. }
  43. }
  44. return true;
  45. };
  46. static auto primes = seq(1, 1 << 20) | filter(isPrimeSlow) | as<vector>();
  47. static auto stopc(int n) {
  48. return [=](int d) { return d * d > n; };
  49. }
  50. static auto divides(int n) {
  51. return [=](int d) { return 0 == n % d; };
  52. }
  53. static auto isPrime = [](int n) {
  54. return from(primes) | until(stopc(n)) | filter(divides(n)) | isEmpty;
  55. };
  56. static auto factors = [](int n) {
  57. return from(primes) | until(stopc(n)) | filter(divides(n)) | count;
  58. };
  59. static auto factorsSlow = [](int n) {
  60. return from(primes) | filter(divides(n)) | count;
  61. };
  62. static auto sleepyWork = [](int i) {
  63. const auto sleepyTime = std::chrono::microseconds(100);
  64. std::this_thread::sleep_for(sleepyTime);
  65. return i;
  66. };
  67. static auto sleepAndWork = [](int i) { return factorsSlow(i) + sleepyWork(i); };
  68. auto start = 1 << 20;
  69. auto v = seq(start) | take(1 << 20) | as<vector>();
  70. auto small = from(v) | take(1 << 12);
  71. auto medium = from(v) | take(1 << 14);
  72. auto large = from(v) | take(1 << 18);
  73. auto huge = from(v);
  74. auto chunks = chunked(v);
  75. BENCH_GEN(small | map(factorsSlow) | sum);
  76. BENCH_GEN_REL(small | parallel(map(factorsSlow)) | sum);
  77. BENCHMARK_DRAW_LINE();
  78. BENCH_GEN(small | map(factors) | sum);
  79. BENCH_GEN_REL(small | parallel(map(factors)) | sum);
  80. BENCHMARK_DRAW_LINE();
  81. BENCH_GEN(large | map(factors) | sum);
  82. BENCH_GEN_REL(large | parallel(map(factors)) | sum);
  83. BENCHMARK_DRAW_LINE();
  84. auto ch = chunks;
  85. auto cat = concat;
  86. BENCH_GEN(huge | filter(isPrime) | count);
  87. BENCH_GEN_REL(ch | cat | filter(isPrime) | count);
  88. BENCH_GEN_REL(ch | parallel(cat | filter(isPrime)) | count);
  89. BENCH_GEN_REL(ch | parallel(cat | filter(isPrime) | sub(count)) | sum);
  90. BENCHMARK_DRAW_LINE();
  91. BENCH_GEN(small | map(sleepAndWork) | sum);
  92. BENCH_GEN_REL(small | parallel(map(sleepAndWork)) | sum);
  93. BENCHMARK_DRAW_LINE();
  94. const int fibs = 1000;
  95. BENCH_GEN(seq(1, fibs) | map([](int) { return fib(kFib); }) | sum);
  96. // clang-format off
  97. BENCH_GEN_REL(
  98. seq(1, fibs)
  99. | parallel(map([](int) { return fib(kFib); }) | sub(sum))
  100. | sum);
  101. // clang-format on
  102. BENCH_GEN_REL([] {
  103. // clang-format off
  104. auto threads = seq(1, int(FLAGS_threads))
  105. | map([](int i) {
  106. return std::thread([=] {
  107. return range(
  108. (i + 0) * fibs / FLAGS_threads, (i + 1) * fibs / FLAGS_threads)
  109. | map([](int) { return fib(kFib); })
  110. | sum;
  111. });
  112. })
  113. | as<vector>();
  114. from(threads) | [](std::thread &thread) { thread.join(); };
  115. // clang-format on
  116. return 1;
  117. }());
  118. BENCHMARK_DRAW_LINE();
  119. #if 0
  120. ============================================================================
  121. folly/gen/test/ParallelBenchmark.cpp relative time/iter iters/s
  122. ============================================================================
  123. small | map(factorsSlow) | sum 4.59s 217.87m
  124. small | parallel(map(factorsSlow)) | sum 1588.86% 288.88ms 3.46
  125. ----------------------------------------------------------------------------
  126. small | map(factors) | sum 9.62ms 103.94
  127. small | parallel(map(factors)) | sum 89.15% 10.79ms 92.66
  128. ----------------------------------------------------------------------------
  129. large | map(factors) | sum 650.52ms 1.54
  130. large | parallel(map(factors)) | sum 53.82% 1.21s 827.41m
  131. ----------------------------------------------------------------------------
  132. huge | filter(isPrime) | count 295.93ms 3.38
  133. ch | cat | filter(isPrime) | count 99.76% 296.64ms 3.37
  134. ch | parallel(cat | filter(isPrime)) | count 142.75% 207.31ms 4.82
  135. ch | parallel(cat | filter(isPrime) | sub(count 1538.50% 19.24ms 51.99
  136. ----------------------------------------------------------------------------
  137. small | map(sleepAndWork) | sum 5.37s 186.18m
  138. small | parallel(map(sleepAndWork)) | sum 1840.38% 291.85ms 3.43
  139. ----------------------------------------------------------------------------
  140. seq(1, fibs) | map([](int) { return fib(kFib); 1.49s 669.53m
  141. seq(1, fibs) | parallel(map([](int) { return fi 1698.07% 87.96ms 11.37
  142. [] { auto threads = seq(1, int(FLAGS_threads)) 1571.16% 95.06ms 10.52
  143. ----------------------------------------------------------------------------
  144. ============================================================================
  145. #endif
  146. int main(int argc, char* argv[]) {
  147. gflags::ParseCommandLineFlags(&argc, &argv, true);
  148. folly::runBenchmarks();
  149. return 0;
  150. }