Last active
October 8, 2023 16:34
-
-
Save isidorostsa/7426389295f329fa0feaabb55639d6bb to your computer and use it in GitHub Desktop.
The C++ code used to benchmark the performance gains of relocating containers "trivially"
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define ANKERL_NANOBENCH_IMPLEMENT | |
#include "nanobench.h" | |
#include <hpx/init.hpp> | |
#include <hpx/parallel/algorithms/uninitialized_relocate.hpp> | |
#include <fstream> | |
#include <iostream> | |
#include <forward_list> | |
#include <memory> | |
#include <random> | |
#include <vector> | |
using hpx::experimental::uninitialized_relocate_n; | |
std::tuple containers = | |
std::make_tuple(std::vector<int>{}, std::forward_list<int>{}, | |
std::unique_ptr<int>{}, std::shared_ptr<int>{}); | |
ankerl::nanobench::Bench bench; | |
using TR = int; | |
using NTR = uint; | |
HPX_DECLARE_TRIVIALLY_RELOCATABLE(std::vector<TR>); | |
HPX_DECLARE_TRIVIALLY_RELOCATABLE(std::forward_list<TR>); | |
HPX_DECLARE_TRIVIALLY_RELOCATABLE(std::unique_ptr<TR>); | |
HPX_DECLARE_TRIVIALLY_RELOCATABLE(std::shared_ptr<TR>); | |
template <typename T, typename TR_NTR, typename Ex> | |
std::vector<std::string> get_strings(size_t size) { | |
std::vector<std::string> strings; | |
if constexpr (std::is_same_v<T, std::vector<TR_NTR>>) { | |
strings.push_back("std::vector"); | |
} else if constexpr (std::is_same_v<T, std::forward_list<TR_NTR>>) { | |
strings.push_back("std::forward_list"); | |
} else if constexpr (std::is_same_v<T, std::unique_ptr<TR_NTR>>) { | |
strings.push_back("std::unique_ptr"); | |
} else if constexpr (std::is_same_v<T, std::shared_ptr<TR_NTR>>) { | |
strings.push_back("std::shared_ptr"); | |
} | |
if constexpr (std::is_same_v<TR_NTR, TR>) { | |
strings.push_back("trivial"); | |
} else if constexpr (std::is_same_v<TR_NTR, NTR>) { | |
strings.push_back("non-trivial"); | |
} | |
if constexpr (std::is_same_v<Ex, hpx::execution::sequenced_policy>) { | |
strings.push_back("sequenced"); | |
} else if constexpr (std::is_same_v<Ex, hpx::execution::parallel_policy>) { | |
strings.push_back("parallel"); | |
} | |
strings.push_back(std::to_string(size)); | |
return strings; | |
} | |
template <typename Cont, typename TR_NTR> | |
struct is_un_or_sh_ptr | |
: std::bool_constant<std::is_same_v<Cont, std::unique_ptr<TR_NTR>> || | |
std::is_same_v<Cont, std::shared_ptr<TR_NTR>>> {}; | |
template <typename T, typename TR_NTR> void fill_up(T *ptr, size_t size) { | |
ankerl::nanobench::Rng rng; | |
if constexpr (is_un_or_sh_ptr<T, TR_NTR>::value) { | |
for (size_t i = 0; i < size; ++i) { | |
new (ptr + i) T{new TR_NTR{rng() % 128}}; | |
} | |
} else { | |
for (size_t i = 0; i < size; ++i) { | |
new (ptr + i) T{rng() % 128, 2, 3, 4, 5}; | |
} | |
} | |
} | |
template <typename T, typename TR_NTR, typename Ex> auto test(int size) { | |
std::byte *buffer1 = static_cast<std::byte *>(std::malloc(size * sizeof(T))); | |
std::byte *buffer2 = static_cast<std::byte *>(std::malloc(size * sizeof(T))); | |
T *v_ptr = reinterpret_cast<T *>(buffer1); | |
fill_up<T, TR_NTR>(v_ptr, size); | |
T *v_ptr2 = reinterpret_cast<T *>(buffer2); | |
ankerl::nanobench::Config cfg; | |
auto strings = get_strings<T, TR_NTR, Ex>(size); | |
std::string name = strings[1] + " relocation of " + strings[0]; | |
std::string fname = "./results/" + strings[1] + "_" + strings[0] + ".json"; | |
std::fstream file(fname, std::ios::out); | |
ankerl::nanobench::Bench() | |
.config(cfg) | |
.context("container", strings[0]) | |
.context("triviality", strings[1]) | |
.context("execution", strings[2]) | |
.context("size", strings[3]) | |
.name(name) | |
.run([&] { | |
auto a = uninitialized_relocate_n(Ex{}, v_ptr, size, v_ptr2); | |
ankerl::nanobench::doNotOptimizeAway(a); | |
auto b = uninitialized_relocate_n(Ex{}, v_ptr2, size, v_ptr); | |
ankerl::nanobench::doNotOptimizeAway(b); | |
}) | |
.render(ankerl::nanobench::templates::pyperf(), file); | |
std::free(buffer1); | |
std::free(buffer2); | |
} | |
#define TEST(Cont, TR_NTR, Ex, size) test<Cont<TR_NTR>, TR_NTR, Ex>(size) | |
#define TEST_OVER_CONT(TR_NTR, Ex, size) \ | |
TEST(std::vector, TR_NTR, Ex, size); \ | |
TEST(std::forward_list, TR_NTR, Ex, size); \ | |
TEST(std::unique_ptr, TR_NTR, Ex, size); \ | |
TEST(std::shared_ptr, TR_NTR, Ex, size); | |
#define TEST_OVER_CONT_TRIVIALITY(Ex, size) \ | |
TEST_OVER_CONT(TR, Ex, size); \ | |
TEST_OVER_CONT(NTR, Ex, size); | |
#define TEST_OVER_CONT_TRIVIALITY_EXECUTION(size) \ | |
TEST_OVER_CONT_TRIVIALITY(hpx::execution::sequenced_policy, size); | |
// TEST_OVER_CONT_TRIVIALITY(hpx::execution::parallel_policy, size); | |
int hpx_main(int argc, char **argv) { | |
size_t size = atoi(argv[1]); | |
TEST_OVER_CONT_TRIVIALITY_EXECUTION(size) | |
return hpx::finalize(); | |
} | |
int main(int argc, char *argv[]) { | |
return hpx::local::init(hpx_main, argc, argv); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
size_of_buffer_in_objects | type | trivial_relocation_speedup | |
---|---|---|---|
100 | unique_ptr | 8.3 | |
100 | shared_ptr | 3.33 | |
100 | forward_list | 2.97 | |
100 | vector | 6.79 | |
1000 | unique_ptr | 15.96 | |
1000 | shared_ptr | 5.75 | |
1000 | forward_list | 4.83 | |
1000 | vector | 6.34 | |
10000 | unique_ptr | 9.52 | |
10000 | shared_ptr | 6.35 | |
10000 | forward_list | 5.18 | |
10000 | vector | 6.47 | |
100000 | unique_ptr | 4.28 | |
100000 | shared_ptr | 0.94 | |
100000 | forward_list | 2.16 | |
100000 | vector | 1.16 | |
1000000 | unique_ptr | 1.59 | |
1000000 | shared_ptr | 1.24 | |
1000000 | forward_list | 0.86 | |
1000000 | vector | 1.31 | |
10000000 | unique_ptr | 1.44 | |
10000000 | shared_ptr | 1.15 | |
10000000 | vector | 1.21 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment