From 7b74328603db35958badff31a52f4def871e29ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ciro=20Santilli=20=E5=85=AD=E5=9B=9B=E4=BA=8B=E4=BB=B6=20?= =?UTF-8?q?=E6=B3=95=E8=BD=AE=E5=8A=9F?= Date: Mon, 2 Dec 2019 00:00:00 +0000 Subject: [PATCH] c++ parallel sort algorithm example --- README.adoc | 7 +++++ path_properties.py | 7 +++++ userland/cpp/parallel_sort.cpp | 51 ++++++++++++++++++++++++++++++++++ userland/cpp/random.cpp | 3 +- 4 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 userland/cpp/parallel_sort.cpp diff --git a/README.adoc b/README.adoc index 80de56d..1d48c69 100644 --- a/README.adoc +++ b/README.adoc @@ -14020,6 +14020,13 @@ Bibliography: * https://stackoverflow.com/questions/31978324/what-exactly-is-stdatomic/58904448#58904448 "What exactly is std::atomic?" +[[cpp-parallel-algorithms]] +===== C++ parallel algorithms + +https://stackoverflow.com/questions/51031060/are-c17-parallel-algorithms-implemented-already/55989883#55989883 + +link:userland/cpp/parallel_sort.cpp[] + [[cpp-standards]] ==== C++ standards diff --git a/path_properties.py b/path_properties.py index 5203459..37e1d53 100644 --- a/path_properties.py +++ b/path_properties.py @@ -56,6 +56,7 @@ class PathProperties: # For some reason QEMU fails with SIGSEGV on int syscalls in x86_64. 'qemu_x86_64_int_syscall': False, 'interactive': False, + 'minimum_gcc_version': (0, 0, 0), # The script takes a perceptible amount of time to run. Possibly an infinite loop. 'more_than_1s': False, # The path should not be built. E.g., it is symlinked into multiple archs. @@ -153,6 +154,9 @@ class PathProperties: }, } + # TODO maybe extract automatically from GCC executable? + current_gcc_version = (7, 3, 0) + ''' Encodes properties of userland and baremetal paths. For directories, it applies to all files under the directory. @@ -227,6 +231,8 @@ class PathProperties: 'cpus' in self['test_run_args'] and self['test_run_args']['cpus'] > 1 ) + ) and not ( + self['minimum_gcc_version'] > self.current_gcc_version ) ) @@ -631,6 +637,7 @@ path_properties_tuples = ( }, ), 'count.cpp': {'more_than_1s': True}, + 'parallel_sort.cpp': {'minimum_gcc_version': (9, 0, 0)}, 'sleep_for.cpp': { 'more_than_1s': True, }, diff --git a/userland/cpp/parallel_sort.cpp b/userland/cpp/parallel_sort.cpp new file mode 100644 index 0000000..b782594 --- /dev/null +++ b/userland/cpp/parallel_sort.cpp @@ -0,0 +1,51 @@ +// https://cirosantilli.com/linux-kernel-module-cheat#cpp-parallel-algorithms + +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) { + using clk = std::chrono::high_resolution_clock; + decltype(clk::now()) start, end; + std::vector input_parallel, input_serial; + unsigned int seed; + unsigned long long n; + + // CLI arguments; + std::uniform_int_distribution zero_ull_max(0); + if (argc > 1) { + n = std::strtoll(argv[1], NULL, 0); + } else { + n = 10; + } + if (argc > 2) { + seed = std::stoi(argv[2]); + } else { + seed = std::random_device()(); + } + + // Calculate random inpu. + std::mt19937 prng(seed); + for (unsigned long long i = 0; i < n; ++i) { + input_parallel.push_back(zero_ull_max(prng)); + } + input_serial = input_parallel; + + // Sort and time parallel. + start = clk::now(); + std::sort(std::execution::par_unseq, input_parallel.begin(), input_parallel.end()); + end = clk::now(); + std::cout << "parallel " << std::chrono::duration(end - start).count() << " s" << std::endl; + + // Sort and time serial. + start = clk::now(); + std::sort(std::execution::seq, input_serial.begin(), input_serial.end()); + end = clk::now(); + std::cout << "serial " << std::chrono::duration(end - start).count() << " s" << std::endl; + + assert(input_parallel == input_serial); +} diff --git a/userland/cpp/random.cpp b/userland/cpp/random.cpp index 742d582..9bc8ece 100644 --- a/userland/cpp/random.cpp +++ b/userland/cpp/random.cpp @@ -6,7 +6,8 @@ int main(int argc, char **argv) { // Potentially expensive /dev/urandom read that waits for entropy. std::random_device dev; - std::mt19937 prng(dev()); + auto seed = dev(); + std::mt19937 prng(seed); std::uniform_int_distribution zero_ull_max(0); std::uniform_int_distribution one_to_six(1, 6);