From 49c375c98525d5552125e18f8a52fa5d59b5e624 Mon Sep 17 00:00:00 2001 From: "github-classroom[bot]" <66690702+github-classroom[bot]@users.noreply.github.com> Date: Fri, 3 Oct 2025 13:57:38 +0000 Subject: [PATCH 1/4] Setting up GitHub Classroom Feedback From a321606e8c78cf190b743d7e09ca69bb550606d4 Mon Sep 17 00:00:00 2001 From: "github-classroom[bot]" <66690702+github-classroom[bot]@users.noreply.github.com> Date: Fri, 3 Oct 2025 13:57:41 +0000 Subject: [PATCH 2/4] add deadline --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 3887682..d757b35 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ +[![Review Assignment Due Date](https://classroom.github.com/assets/deadline-readme-button-22041afd0340ce965d47ae6ef1cefeee28c7c493a6346c4f15d667ab976d596c.svg)](https://classroom.github.com/a/urO9t9_z) # Лабораторная работа № 1: определение достижимости параллелизма и реализация параллельных алгоритмов. Шаги выполнения: From b7ff022297918cf041e580a31fde2500a8f2f6ce Mon Sep 17 00:00:00 2001 From: Ivan Sokolov Date: Tue, 7 Oct 2025 01:45:20 +0300 Subject: [PATCH 3/4] It works & is faster --- .gitignore | 2 + .idea/.gitignore | 8 - CMakeLists.txt | 6 + CMakePresets.json | 19 ++ a.out | Bin 0 -> 37768 bytes bfs.cpp | 155 +++++++++++++++ digraph.hpp | 31 +++ main.cpp | 184 +++++++++++++----- Graph.cpp => old/Graph.cpp | 0 Graph.h => old/Graph.h | 0 .../RandomGraphGenerator.cpp | 0 .../RandomGraphGenerator.h | 0 old/main.cpp | 63 ++++++ svo.hpp | 99 ++++++++++ tmp/results.txt | 40 ---- 15 files changed, 505 insertions(+), 102 deletions(-) create mode 100644 .gitignore delete mode 100644 .idea/.gitignore create mode 100644 CMakeLists.txt create mode 100644 CMakePresets.json create mode 100755 a.out create mode 100644 bfs.cpp create mode 100644 digraph.hpp rename Graph.cpp => old/Graph.cpp (100%) rename Graph.h => old/Graph.h (100%) rename RandomGraphGenerator.cpp => old/RandomGraphGenerator.cpp (100%) rename RandomGraphGenerator.h => old/RandomGraphGenerator.h (100%) create mode 100644 old/main.cpp create mode 100644 svo.hpp delete mode 100644 tmp/results.txt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c214228 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +build/ +old/tmp/ \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 13566b8..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Editor-based HTTP Client requests -/httpRequests/ -# Datasource local storage ignored files -/dataSources/ -/dataSources.local.xml diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..6134542 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 3.28) +project(parbfs CXX) +set(CMAKE_CXX_STANDARD 23) + +add_executable(parbfs main.cpp bfs.cpp) +target_link_libraries(parbfs fmt) \ No newline at end of file diff --git a/CMakePresets.json b/CMakePresets.json new file mode 100644 index 0000000..e3f212d --- /dev/null +++ b/CMakePresets.json @@ -0,0 +1,19 @@ +{ + "version": 3, + "cmakeMinimumRequired": { + "major": 3, + "minor": 28, + "patch": 0 + }, + "configurePresets": [ + { + "name": "default", + "generator": "Ninja Multi-Config", + "binaryDir": "${sourceDir}/build", + "cacheVariables": { + "CMAKE_EXPORT_COMPILE_COMMANDS": "ON", + "CMAKE_CXX_FLAGS": "-Wall -Wextra -Wattributes" + } + } + ] +} \ No newline at end of file diff --git a/a.out b/a.out new file mode 100755 index 0000000000000000000000000000000000000000..b389ff229c13b5114170cd0d88c96ebcc01d720c GIT binary patch literal 37768 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 J8bcbW{9iG+`*i>S literal 0 HcmV?d00001 diff --git a/bfs.cpp b/bfs.cpp new file mode 100644 index 0000000..23d936c --- /dev/null +++ b/bfs.cpp @@ -0,0 +1,155 @@ +#include "digraph.hpp" +#include +#include +#include +#include +#include + +void bfs(const digraph& g, std::span depths) { + assert(std::ssize(depths) == g.num_verts()); + std::queue q; + q.push(0); + depths[0] = 0; + std::fill(depths.begin()+1, depths.end(), -1); + do { + int v = q.front(); + q.pop(); + for (int n: g.adj[v]) { + if (depths[n] == -1) { + depths[n] = depths[v] + 1; + q.push(n); + } + } + } while (!q.empty()); +} + +struct parbfs { + const digraph& g; + std::span depths; + + struct block { + constexpr static int max_size = 128; + int entries[max_size]; + + explicit block() { + std::fill(std::begin(entries), std::end(entries), -1); + } + + int size() const { + return std::count_if( + std::begin(entries), std::end(entries), + [](int i) { return i != -1; }); + } + }; + + struct { + std::mutex mutex; + std::condition_variable more; + std::queue> blocks; + int empty_workers = 0; + bool done = false; + } q; + + std::vector threads; + + explicit parbfs(int n_threads, const digraph& g, std::span depths): + g(g), + depths(depths), + threads(n_threads) + { + auto initial = std::make_unique(); + initial->entries[0] = 0; + q.blocks.push(std::move(initial)); + + for (int i = 0; i < n_threads; ++i) { + threads[i] = std::jthread(&parbfs::worker, this); + } + } + + std::unique_ptr pop_block() { + std::unique_lock lk(q.mutex); + if (++q.empty_workers == std::ssize(threads) && q.blocks.empty()) { + q.done = true; + q.more.notify_all(); + return nullptr; + } + q.more.wait(lk, [&] { return !q.blocks.empty() || q.done; }); + if (q.done) { + return nullptr; + } + auto result = std::move(q.blocks.front()); + q.blocks.pop(); + --q.empty_workers; + return result; + } + + void push_block(std::unique_ptr block) { + std::unique_lock lk(q.mutex); + q.blocks.push(std::move(block)); + q.more.notify_one(); + } + + constexpr static int seqcst = __ATOMIC_SEQ_CST; + + void worker() { + int out_size = 0; + std::unique_ptr out = nullptr; + + auto push_out = [&] { + if (out) { + push_block(std::move(out)); + out_size = 0; + } + }; + + auto push_vert = [&](int vert) { + if (!out) { + assert(out_size == 0); + out = std::make_unique(); + } + assert(out_size < block::max_size); + out->entries[out_size++] = vert; + if (out_size == block::max_size) { + push_out(); + } + }; + + auto process_vert = [&](int src) { + const int src_depth = __atomic_load_n(&depths[src], seqcst); + const int new_depth = src_depth + 1; + for (int dst: g.adj[src]) { + int dst_depth = __atomic_load_n(&depths[dst], seqcst); + if (dst_depth != -1 && dst_depth <= new_depth) { + continue; + } + cmpxchg: + bool updated = __atomic_compare_exchange_n( + &depths[dst], &dst_depth, new_depth, + true, seqcst, seqcst); + if (updated) { + push_vert(dst); + } else { + assert(dst_depth != -1); + if (dst_depth > new_depth) { + goto cmpxchg; + } + } + } + }; + + while (auto in = pop_block()) { + for (int src: in->entries) { + if (src == -1) { break; } + process_vert(src); + } + push_out(); + } + } +}; + +void parallel_bfs(int n_threads, const digraph& g, std::span depths) { + depths[0] = 0; + std::fill(depths.begin()+1, depths.end(), -1); + assert(std::ssize(depths) == g.num_verts()); + parbfs parbfs(n_threads, g, depths); +} \ No newline at end of file diff --git a/digraph.hpp b/digraph.hpp new file mode 100644 index 0000000..4ecd21c --- /dev/null +++ b/digraph.hpp @@ -0,0 +1,31 @@ +#pragma once +#include "svo.hpp" +#include +#include +#include + +struct digraph { + std::vector> adj; + int num_edges = 0; + + explicit digraph(int verts): adj(verts) {} + + int num_verts() const { return std::ssize(adj); } + + bool maybe_add_edge(int from, int to) { + assert(from >= 0 && from < num_verts()); + assert(to >= 0 && to < num_verts()); + if (from != to) { + auto& v = adj[from]; + if (std::find(v.begin(), v.end(), to) == v.end()) { + v.emplace_back(to); + ++num_edges; + return true; + } + } + return false; + } +}; + +void bfs(const digraph&, std::span depths); +void parallel_bfs(int n_threads, const digraph&, std::span depths); \ No newline at end of file diff --git a/main.cpp b/main.cpp index a4c0368..b0f3dfc 100644 --- a/main.cpp +++ b/main.cpp @@ -1,60 +1,136 @@ +#include "digraph.hpp" +#include +#include #include -#include -#include -#include -#include -#include "Graph.h" -#include "RandomGraphGenerator.h" - -static long long executeSerialBfsAndGetTime(Graph& g) { - auto start = std::chrono::steady_clock::now(); - g.bfs(0); - auto end = std::chrono::steady_clock::now(); - return std::chrono::duration_cast(end - start).count(); -} +#include +#include +#include +#include + +#if 1 +struct xorshift128 { + using result_type = uint64_t; + constexpr static result_type max() { return UINT64_MAX; } + constexpr static result_type min() { return 0; } + + explicit xorshift128() = default; + explicit xorshift128(uint64_t s): a(s), b(s) {} + explicit xorshift128(uint64_t a, uint64_t b): a(a), b(b) {} + + uint64_t a = 0xfe48ec23c5fb18e0; + uint64_t b = 0xac5f64acb55eda12; + + result_type operator()() { + uint64_t x = a, y = b; + a = b; + x ^= x << 23; + b = x ^ y ^ (x >> 17) ^ (y >> 26); + return b + y; + } +}; +using rng = xorshift128; +#else +#include +using rng = std::mt19937_64; +#endif + +template +[[gnu::noinline]] +digraph make_random_digraph(Rng& rng, int n_verts, int n_edges) { + assert(n_verts > 1); + assert(n_edges >= n_verts-1); + assert(n_edges <= long(n_verts) * (n_verts - 1)); + + digraph g(n_verts); + + { + std::vector perm(n_verts); + std::iota(perm.begin(), perm.end(), 0); + std::shuffle(perm.begin(), perm.end(), rng); + for (int i = 1; i < n_verts; ++i) { + g.maybe_add_edge(perm[i-1], perm[i]); + } + if (n_edges >= n_verts) { + g.maybe_add_edge(perm[n_verts-1], perm[0]); + } + } + + std::uniform_int_distribution dist(0, n_verts-1); + +#if 1 + for (int from = 0; from < n_verts; ++from) { + int wantout = std::min(n_verts-1, n_edges / n_verts); + while (std::ssize(g.adj[from]) < wantout) { + g.maybe_add_edge(from, dist(rng)); + } + } +#endif -static long long executeParallelBfsAndGetTime(Graph& g) { - auto start = std::chrono::steady_clock::now(); - g.parallelBFS(0); // заглушка - auto end = std::chrono::steady_clock::now(); - return std::chrono::duration_cast(end - start).count(); + while (g.num_edges < n_edges) { + g.maybe_add_edge(dist(rng), dist(rng)); + } + + assert(g.num_edges == n_edges); + return g; } +struct timer { + using clock = std::chrono::steady_clock; + clock::time_point started = clock::now(); + + using dmilliseconds = std::chrono::duration; + + dmilliseconds measure() const { + return std::chrono::duration_cast(clock::now() - started); + }; +}; + int main() { - try { - std::vector sizes = {10, 100, 1000, 10000, 10000, 50000, 100000, 1000000, 2000000, 20000000}; - std::vector connections = {50, 500, 5000, 50000, 100000, 1000000, 1000000, 10000000, 10000000, 50000000}; - - std::mt19937_64 r(42); - - std::filesystem::create_directories("tmp"); - std::ofstream fw("tmp/results.txt"); - if (!fw) { - std::cerr << "Failed to open tmp/results.txt for writing\n"; - return 1; - } - - RandomGraphGenerator gen; - - for (size_t i = 0; i < sizes.size(); ++i) { - std::cout << "--------------------------\n"; - std::cout << "Generating graph of size " << sizes[i] << " ... wait\n"; - Graph g = gen.generateGraph(r, sizes[i], connections[i]); - std::cout << "Generation completed!\nStarting bfs\n"; - long long serialTime = executeSerialBfsAndGetTime(g); - long long parallelTime = executeParallelBfsAndGetTime(g); - - fw << "Times for " << sizes[i] << " vertices and " << connections[i] << " connections: "; - fw << "\nSerial: " << serialTime; - fw << "\nParallel: " << parallelTime; - fw << "\n--------\n"; - fw.flush(); - } - - std::cout << "Done. Results in tmp/results.txt\n"; - } catch (const std::exception& ex) { - std::cerr << "Exception: " << ex.what() << "\n"; - return 2; - } - return 0; + constexpr static struct { int v, e; } configs[] = { + { 10, 50 }, + { 100, 500 }, + { 1000, 5000 }, + { 10'000, 50'000 }, + { 50'000, 1000'000 }, + { 100'000, 1000'000 }, + { 250'000, 249'999 }, + { 2000'000, 10'000'000 }, + { 20'000'000, 50'000'000 }, + { 20'000'000, 100'000'000 }, + { 20'000'000, 500'000'000 }, + }; + + std::vector depths_seq(100'000'000); + std::vector depths_par(100'000'000); + constexpr int n_threads = 4; + + rng rng; + for (auto [v, e]: configs) { + digraph g = make_random_digraph(rng, v, e); + + auto seq_span = std::span(depths_seq).subspan(0, v); + auto par_span = std::span(depths_par).subspan(0, v); + + timer seq_timer; + bfs(g, seq_span); + auto seq_time = seq_timer.measure(); + + timer par_timer; + parallel_bfs(n_threads, g, par_span); + auto par_time = par_timer.measure(); + + bool equal = std::ranges::equal(seq_span, par_span); + + constexpr auto green = fg(fmt::color::green); + constexpr auto red = fg(fmt::color::red); + using namespace std::literals; + + fmt::print( + "{}v / {}e\tseq bfs: {}\tpar bfs ({} threads): {}.\tresult {}\n", + v, e, + styled(seq_time, seq_time < par_time ? green : red), + n_threads, + styled(par_time, par_time < seq_time ? green : red), + equal ? styled("matches"sv, green) : styled("mismatch"sv, red)); + } } \ No newline at end of file diff --git a/Graph.cpp b/old/Graph.cpp similarity index 100% rename from Graph.cpp rename to old/Graph.cpp diff --git a/Graph.h b/old/Graph.h similarity index 100% rename from Graph.h rename to old/Graph.h diff --git a/RandomGraphGenerator.cpp b/old/RandomGraphGenerator.cpp similarity index 100% rename from RandomGraphGenerator.cpp rename to old/RandomGraphGenerator.cpp diff --git a/RandomGraphGenerator.h b/old/RandomGraphGenerator.h similarity index 100% rename from RandomGraphGenerator.h rename to old/RandomGraphGenerator.h diff --git a/old/main.cpp b/old/main.cpp new file mode 100644 index 0000000..033b329 --- /dev/null +++ b/old/main.cpp @@ -0,0 +1,63 @@ +#include +#include +#include +#include +#include +#include "Graph.h" +#include "RandomGraphGenerator.h" + +static long long executeSerialBfsAndGetTime(Graph& g) { + auto start = std::chrono::steady_clock::now(); + g.bfs(0); + auto end = std::chrono::steady_clock::now(); + return std::chrono::duration_cast(end - start).count(); +} + +static long long executeParallelBfsAndGetTime(Graph& g) { + auto start = std::chrono::steady_clock::now(); + g.parallelBFS(0); // заглушка + auto end = std::chrono::steady_clock::now(); + return std::chrono::duration_cast(end - start).count(); +} + +int main() { + try { + std::vector sizes = {10, 100, 1000, 10000, 10000, 50000, 100000, 1000000, 2000000, 20000000}; + std::vector connections = {50, 500, 5000, 50000, 100000, 1000000, 1000000, 10000000, 10000000, 50000000}; + + std::mt19937_64 r(42); + + std::filesystem::create_directories("tmp"); + std::ofstream fw("tmp/results.txt"); + if (!fw) { + std::cerr << "Failed to open tmp/results.txt for writing\n"; + return 1; + } + + RandomGraphGenerator gen; + + for (size_t i = 0; i < sizes.size(); ++i) { + std::cout << "--------------------------\n"; + std::cout << "Generating graph of size " << sizes[i] << " ... wait\n"; + auto started = std::chrono::steady_clock::now(); + Graph g = gen.generateGraph(r, sizes[i], connections[i]); + auto done = std::chrono::steady_clock::now(); + auto elapsed = std::chrono::duration_cast(done - started); + std::cout << "Generation completed - " << elapsed.count() << "ms\nStarting bfs\n"; + long long serialTime = executeSerialBfsAndGetTime(g); + long long parallelTime = executeParallelBfsAndGetTime(g); + + fw << "Times for " << sizes[i] << " vertices and " << connections[i] << " connections: "; + fw << "\nSerial: " << serialTime; + fw << "\nParallel: " << parallelTime; + fw << "\n--------\n"; + fw.flush(); + } + + std::cout << "Done. Results in tmp/results.txt\n"; + } catch (const std::exception& ex) { + std::cerr << "Exception: " << ex.what() << "\n"; + return 2; + } + return 0; +} \ No newline at end of file diff --git a/svo.hpp b/svo.hpp new file mode 100644 index 0000000..41827ae --- /dev/null +++ b/svo.hpp @@ -0,0 +1,99 @@ +#pragma once +#include +#include +#include +#include + +// Non-feature-complete small vector. It is more compact than in boost. +// It stores inline as many elements as will fit within the size +// of std::vector, minus four bytes +template +class svo_vector { + using large_vector = std::vector; + constexpr static size_t max_small + = std::min(size_t(1), (sizeof(large_vector) - 4) / sizeof(T)); + + union repr { + struct { + // is_small is LSB of the data pointer in std::vector stored in large_storage. + // It will always be 0 when std::vector is live, due to allocator alignment. + // So in the small case, we set it to 1. + bool is_small: 1; + unsigned size: 31; + alignas(T) char storage[sizeof(T) * max_small]; + T elems[max_small]; + } small; + alignas(large_vector) char large_storage[sizeof(large_vector)]; + } repr; + static_assert(sizeof(repr) == sizeof(large_vector)); + + bool is_small() const { + return repr.small.is_small; + } + + T* small_storage() { + return reinterpret_cast(repr.small.storage); + } + + const T* small_storage() const { + return reinterpret_cast(repr.small.storage); + } + + large_vector& large() { + return reinterpret_cast(repr.large_storage); + } + + const large_vector& large() const { + return reinterpret_cast(repr.large_storage); + } + +public: + using value_type = T; + using reference = T&; + using iterator = T*; + + svo_vector() { + repr.small.is_small = true; + repr.small.size = 0; + } + + ~svo_vector() { + if (is_small()) { + std::destroy_n(small_storage(), repr.small.size); + } else { + large().~vector(); + } + } + + svo_vector(svo_vector&&) = delete; + svo_vector(const svo_vector&) = delete; + svo_vector& operator=(svo_vector&&) = delete; + svo_vector& operator=(const svo_vector&) = delete; + + size_t size() const { + return is_small() ? repr.small.size : large().size(); + } + + template + reference emplace_back(Args&&... args) { + if (!is_small()) { + return large().emplace_back(std::forward(args)...); + } + if (repr.small.size < max_small) { + return *new(small_storage() + repr.small.size++) + value_type(std::forward(args)...); + } + large_vector tmp; + tmp.reserve(max_small + 1); + std::move(small_storage(), + small_storage() + repr.small.size, + std::back_inserter(tmp)); + tmp.emplace_back(std::forward(args)...); + std::destroy_n(small_storage(), repr.small.size); + new(repr.large_storage) large_vector(std::move(tmp)); + return large().back(); + } + + auto begin(this auto& v) { return v.is_small() ? v.small_storage() : v.large().data(); } + auto end(this auto& v) { return v.begin() + v.size(); } +}; \ No newline at end of file diff --git a/tmp/results.txt b/tmp/results.txt deleted file mode 100644 index e3145c0..0000000 --- a/tmp/results.txt +++ /dev/null @@ -1,40 +0,0 @@ -Times for 10 vertices and 50 connections: -Serial: 0 -Parallel: 0 --------- -Times for 100 vertices and 500 connections: -Serial: 0 -Parallel: 0 --------- -Times for 1000 vertices and 5000 connections: -Serial: 0 -Parallel: 0 --------- -Times for 10000 vertices and 50000 connections: -Serial: 0 -Parallel: 0 --------- -Times for 10000 vertices and 100000 connections: -Serial: 0 -Parallel: 0 --------- -Times for 50000 vertices and 1000000 connections: -Serial: 2 -Parallel: 0 --------- -Times for 100000 vertices and 1000000 connections: -Serial: 3 -Parallel: 0 --------- -Times for 1000000 vertices and 10000000 connections: -Serial: 90 -Parallel: 0 --------- -Times for 2000000 vertices and 10000000 connections: -Serial: 153 -Parallel: 0 --------- -Times for 20000000 vertices and 50000000 connections: -Serial: 1261 -Parallel: 0 --------- From a1bcd4dbb2cb5cef48d3dfc51b177393db57a91a Mon Sep 17 00:00:00 2001 From: Ivan Sokolov Date: Tue, 7 Oct 2025 12:20:46 +0300 Subject: [PATCH 4/4] 2025-10-07 --- .gitignore | 5 ++- CMakePresets.json | 8 ++++ a.out | Bin 37768 -> 0 bytes bfs.cpp | 97 ++++++++++++++++++++++++---------------------- main.cpp | 22 ++++++++--- result.ipynb | 52 +++++++++++++++++++++++++ 6 files changed, 129 insertions(+), 55 deletions(-) delete mode 100755 a.out create mode 100644 result.ipynb diff --git a/.gitignore b/.gitignore index c214228..8e79e7c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ -build/ -old/tmp/ \ No newline at end of file +build*/ +old/tmp/ +*.csv \ No newline at end of file diff --git a/CMakePresets.json b/CMakePresets.json index e3f212d..f147cef 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -14,6 +14,14 @@ "CMAKE_EXPORT_COMPILE_COMMANDS": "ON", "CMAKE_CXX_FLAGS": "-Wall -Wextra -Wattributes" } + }, + { + "name": "san", + "inherits": "default", + "binaryDir": "${sourceDir}/build-san", + "cacheVariables": { + "CMAKE_CXX_FLAGS": "-fsanitize=address" + } } ] } \ No newline at end of file diff --git a/a.out b/a.out deleted file mode 100755 index b389ff229c13b5114170cd0d88c96ebcc01d720c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37768 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 J8bcbW{9iG+`*i>S diff --git a/bfs.cpp b/bfs.cpp index 23d936c..b852668 100644 --- a/bfs.cpp +++ b/bfs.cpp @@ -5,12 +5,19 @@ #include #include -void bfs(const digraph& g, std::span depths) { +static void reset_depths(const digraph& g [[maybe_unused]], + std::span depths, + int start_vert) { assert(std::ssize(depths) == g.num_verts()); + std::fill_n(depths.begin(), start_vert, -1); + depths[start_vert] = 0; + std::fill(depths.begin() + start_vert + 1, depths.end(), -1); +} + +void bfs(const digraph& g, std::span depths) { + reset_depths(g, depths, 0); std::queue q; q.push(0); - depths[0] = 0; - std::fill(depths.begin()+1, depths.end(), -1); do { int v = q.front(); q.pop(); @@ -28,75 +35,78 @@ struct parbfs { std::span depths; struct block { - constexpr static int max_size = 128; - int entries[max_size]; + constexpr static int max_size = 256; + int verts[max_size]; + }; - explicit block() { - std::fill(std::begin(entries), std::end(entries), -1); - } + int load_depth(int vert) { + return __atomic_load_n(&depths[vert], __ATOMIC_SEQ_CST); + } - int size() const { - return std::count_if( - std::begin(entries), std::end(entries), - [](int i) { return i != -1; }); - } - }; + bool weak_cas_depth(int vert, int* expected, int desired) { + return __atomic_compare_exchange_n( + &depths[vert], expected, desired, + true, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); + } struct { std::mutex mutex; std::condition_variable more; - std::queue> blocks; - int empty_workers = 0; + std::queue> queue; + int idle = 0; bool done = false; } q; - std::vector threads; + std::vector workers; explicit parbfs(int n_threads, const digraph& g, std::span depths): g(g), depths(depths), - threads(n_threads) + workers(n_threads) { auto initial = std::make_unique(); - initial->entries[0] = 0; - q.blocks.push(std::move(initial)); + initial->verts[0] = 0; + initial->verts[1] = -1; + q.queue.push(std::move(initial)); for (int i = 0; i < n_threads; ++i) { - threads[i] = std::jthread(&parbfs::worker, this); + workers[i] = std::jthread(&parbfs::worker, this); } } std::unique_ptr pop_block() { std::unique_lock lk(q.mutex); - if (++q.empty_workers == std::ssize(threads) && q.blocks.empty()) { + if (++q.idle == std::ssize(workers) && q.queue.empty()) { q.done = true; q.more.notify_all(); return nullptr; } - q.more.wait(lk, [&] { return !q.blocks.empty() || q.done; }); + q.more.wait(lk, [&] { return !q.queue.empty() || q.done; }); if (q.done) { + assert(q.queue.empty()); return nullptr; } - auto result = std::move(q.blocks.front()); - q.blocks.pop(); - --q.empty_workers; + auto result = std::move(q.queue.front()); + q.queue.pop(); + --q.idle; return result; } void push_block(std::unique_ptr block) { std::unique_lock lk(q.mutex); - q.blocks.push(std::move(block)); + q.queue.push(std::move(block)); q.more.notify_one(); } - constexpr static int seqcst = __ATOMIC_SEQ_CST; - void worker() { int out_size = 0; std::unique_ptr out = nullptr; auto push_out = [&] { if (out) { + if (out_size != block::max_size) { + out->verts[out_size] = -1; + } push_block(std::move(out)); out_size = 0; } @@ -108,37 +118,32 @@ struct parbfs { out = std::make_unique(); } assert(out_size < block::max_size); - out->entries[out_size++] = vert; + out->verts[out_size++] = vert; if (out_size == block::max_size) { push_out(); } }; auto process_vert = [&](int src) { - const int src_depth = __atomic_load_n(&depths[src], seqcst); + const int src_depth = load_depth(src); const int new_depth = src_depth + 1; for (int dst: g.adj[src]) { - int dst_depth = __atomic_load_n(&depths[dst], seqcst); + int dst_depth = load_depth(dst); if (dst_depth != -1 && dst_depth <= new_depth) { continue; } - cmpxchg: - bool updated = __atomic_compare_exchange_n( - &depths[dst], &dst_depth, new_depth, - true, seqcst, seqcst); - if (updated) { - push_vert(dst); - } else { - assert(dst_depth != -1); - if (dst_depth > new_depth) { - goto cmpxchg; + do { + if (weak_cas_depth(dst, &dst_depth, new_depth)) { + push_vert(dst); + break; } - } + assert(dst_depth != -1); + } while (dst_depth > new_depth); } }; while (auto in = pop_block()) { - for (int src: in->entries) { + for (int src: in->verts) { if (src == -1) { break; } process_vert(src); } @@ -148,8 +153,6 @@ struct parbfs { }; void parallel_bfs(int n_threads, const digraph& g, std::span depths) { - depths[0] = 0; - std::fill(depths.begin()+1, depths.end(), -1); - assert(std::ssize(depths) == g.num_verts()); + reset_depths(g, depths, 0); parbfs parbfs(n_threads, g, depths); } \ No newline at end of file diff --git a/main.cpp b/main.cpp index b0f3dfc..bbf0bb2 100644 --- a/main.cpp +++ b/main.cpp @@ -2,11 +2,13 @@ #include #include #include -#include -#include #include #include +#include +#include +#include +namespace { #if 1 struct xorshift128 { using result_type = uint64_t; @@ -84,6 +86,7 @@ struct timer { return std::chrono::duration_cast(clock::now() - started); }; }; +} // namespace int main() { constexpr static struct { int v, e; } configs[] = { @@ -93,20 +96,25 @@ int main() { { 10'000, 50'000 }, { 50'000, 1000'000 }, { 100'000, 1000'000 }, - { 250'000, 249'999 }, + { 250'000, 250'000 }, { 2000'000, 10'000'000 }, { 20'000'000, 50'000'000 }, { 20'000'000, 100'000'000 }, { 20'000'000, 500'000'000 }, }; - std::vector depths_seq(100'000'000); - std::vector depths_par(100'000'000); + std::vector depths_seq(20'000'000); + std::vector depths_par(20'000'000); constexpr int n_threads = 4; - rng rng; + std::ofstream csv("out.csv"); + csv << "v,e,buildtime,seqtime,partime,threads\n"; + for (auto [v, e]: configs) { + rng rng; + timer build_timer; digraph g = make_random_digraph(rng, v, e); + auto build_time = build_timer.measure(); auto seq_span = std::span(depths_seq).subspan(0, v); auto par_span = std::span(depths_par).subspan(0, v); @@ -132,5 +140,7 @@ int main() { n_threads, styled(par_time, par_time < seq_time ? green : red), equal ? styled("matches"sv, green) : styled("mismatch"sv, red)); + csv << fmt::format("{},{},{},{},{},{}\n", + v, e, build_time.count(), seq_time.count(), par_time.count(), n_threads); } } \ No newline at end of file diff --git a/result.ipynb b/result.ipynb new file mode 100644 index 0000000..ecbb5e7 --- /dev/null +++ b/result.ipynb @@ -0,0 +1,52 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "9d7ced3e", + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import plotly.graph_objects as go\n", + "import plotly.express as px\n", + "import numpy as np" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "380f54e7", + "metadata": {}, + "outputs": [], + "source": [ + "data = pd.read_csv('out.csv')\n", + "data['ve'] = data['e']\n", + "data['ratio'] = data['seqtime'] / data['partime']\n", + "display(data)\n", + "px.line(data, x='ve', y=['seqtime', 'partime'])" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}