From 4fa77d5288992eb6a143c5aebd8ff736bccd3df3 Mon Sep 17 00:00:00 2001 From: Raphael Steiner Date: Tue, 3 Mar 2026 09:24:08 +0100 Subject: [PATCH 1/8] An example --- GarphExample.dot | 138 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 GarphExample.dot diff --git a/GarphExample.dot b/GarphExample.dot new file mode 100644 index 0000000..9c7a56b --- /dev/null +++ b/GarphExample.dot @@ -0,0 +1,138 @@ +digraph QNetwork{ + node [shape=plaintext;] + edge [shape=plaintext; arrowhead="vee"; fontsize="8";] + + subgraph Info{ + layer="0"; + + NetworkInfo [ + label=< + + + +
QNetwork Information
+ + + + + +
Number of Workers4
Number of Channels4
Buffer Size16
Enqueue Frequency8
Max. Push Attempts8
+ > + ]; + } + + subgraph cluster_network{ + label="QNetwork"; + layer="1"; + margin="30"; + + Worker0 [ + label=< + + + + +
Worker 0
Core0
Load0.25
+ > + ]; + + Worker1 [ + label=< + + + + +
Worker 1
Core1
Load0.25
+ > + ]; + + Worker2 [ + label=< + + + + +
Worker 2
Core2
Load0.25
+ > + ]; + + Worker3 [ + label=< + + + + +
Worker 3
Core3
Load0.25
+ > + ]; + + Worker0 -> Worker0 [ + label=< + + + +
Mult.1
Batch4
+ > + ]; + Worker0 -> Worker1 [ + label=< + + + +
Mult.1
Batch4
+ > + ]; + + Worker1 -> Worker2 [ + label=< + + + +
Mult.1
Batch8
+ > + ]; + Worker1 -> Worker3 [ + label=< + + + +
Mult.1
Batch8
+ > + ]; + + Worker2 -> Worker2 [ + label=< + + + +
Mult.1
Batch4
+ > + ]; + Worker2 -> Worker3 [ + label=< + + + +
Mult.1
Batch4
+ > + ]; + + Worker3 -> Worker0 [ + label=< + + + +
Mult.1
Batch8
+ > + ]; + Worker3 -> Worker1 [ + label=< + + + +
Mult.1
Batch8
+ > + ]; + + } +} \ No newline at end of file From f11898a0232ccbf184db857eb7b833cf3ea221f0 Mon Sep 17 00:00:00 2001 From: Raphael Steiner Date: Sun, 29 Mar 2026 19:05:04 +0200 Subject: [PATCH 2/8] workload distribution --- .../Drawing/WorkLoadDistribution.hpp | 87 +++++++++++++++++++ tests/QNetwork.cpp | 60 +++++++++++-- 2 files changed, 140 insertions(+), 7 deletions(-) create mode 100644 include/ParallelPriotityQueue/Drawing/WorkLoadDistribution.hpp diff --git a/include/ParallelPriotityQueue/Drawing/WorkLoadDistribution.hpp b/include/ParallelPriotityQueue/Drawing/WorkLoadDistribution.hpp new file mode 100644 index 0000000..8dffe05 --- /dev/null +++ b/include/ParallelPriotityQueue/Drawing/WorkLoadDistribution.hpp @@ -0,0 +1,87 @@ +/* +Copyright 2026 Raphael S. Steiner + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +@author Raphael S. Steiner +*/ + +#pragma once + +#include +#include + +#include "ParallelPriotityQueue/QNetwork.hpp" + +namespace spapq { + +template +std::array workLoadDistribution(const QNetwork &netw) { + assert(netw.isValidQNetwork()); + assert(netw.isStronglyConnected()); + + std::array weights; + for (double &val : weights) { val = 0.0; } + for (std::size_t worker = 0U; worker < workers; ++worker) { + std::size_t totalWeight = 0U; + + std::size_t batchSizeGCD = 0U; + for (std::size_t edge = netw.vertexPointer_[worker]; edge < netw.vertexPointer_[worker + 1]; ++edge) { + batchSizeGCD = std::gcd(batchSizeGCD, netw.batchSize_[edge]); + } + + for (std::size_t edge = netw.vertexPointer_[worker]; edge < netw.vertexPointer_[worker + 1U]; ++edge) { + std::size_t weight = netw.multiplicities_[edge] * (netw.batchSize_[edge] / batchSizeGCD); + + totalWeight += weight; + weights[edge] = static_cast(weight); + } + + for (std::size_t edge = netw.vertexPointer_[worker]; edge < netw.vertexPointer_[worker + 1U]; ++edge) { + weights[edge] /= static_cast(totalWeight); + } + } + + std::array targets; + for (std::size_t edge = 0U; edge < targets.size(); ++edge) { targets[edge] = netw.target(edge); } + + std::array dist; + for (double &val : dist) { val = 1.0 / static_cast(workers); } + + std::array distAfterIteration; + constexpr double epsilon = 1e-10; + bool loop = true; + while (loop) { + loop = false; + for (double &val : distAfterIteration) { val = 0.0; } + + for (std::size_t worker = 0U; worker < workers; ++worker) { + for (std::size_t edge = netw.vertexPointer_[worker]; edge < netw.vertexPointer_[worker + 1U]; ++edge) { + distAfterIteration[targets[edge]] += dist[worker] * weights[edge]; + } + } + + for (std::size_t worker = 0U; worker < workers; ++worker) { + if (std::abs(dist[worker] - distAfterIteration[worker]) > epsilon) { + loop = true; + break; + } + } + + std::swap(dist, distAfterIteration); + } + + return dist; +} + +} // end namespace spapq diff --git a/tests/QNetwork.cpp b/tests/QNetwork.cpp index 3d0c4e2..8900de7 100644 --- a/tests/QNetwork.cpp +++ b/tests/QNetwork.cpp @@ -1,5 +1,5 @@ /* -Copyright 2025 Raphael S. Steiner +Copyright 2025, 2026 Raphael S. Steiner Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -22,6 +22,7 @@ limitations under the License. #include +#include "ParallelPriotityQueue/Drawing/WorkLoadDistribution.hpp" #include "ParallelPriotityQueue/GraphExamples/FullyConnectedGraph.hpp" #include "ParallelPriotityQueue/GraphExamples/LineGraph.hpp" #include "ParallelPriotityQueue/GraphExamples/PetersenGraph.hpp" @@ -29,8 +30,7 @@ limitations under the License. using namespace spapq; TEST(QNetworkTest, Constructors1) { - constexpr QNetwork<4, 4> netw( - {0, 1, 2, 3, 4}, {1, 2, 3, 0}, {11, 12, 13, 14}, {10, 9, 8, 7}, {2, 4, 6, 8}); + constexpr QNetwork<4, 4> netw({0, 1, 2, 3, 4}, {1, 2, 3, 0}, {11, 12, 13, 14}, {10, 9, 8, 7}, {2, 4, 6, 8}); EXPECT_EQ(netw.numWorkers_, 4); EXPECT_EQ(netw.numChannels_, 4); for (std::size_t i = 0; i < 5; ++i) { EXPECT_EQ(netw.vertexPointer_[i], i); } @@ -396,8 +396,7 @@ TEST(QNetworkTest, Connectivity) { TEST(QNetworkTest, SrcTgt) { constexpr QNetwork<10, 30> netw1 = PETERSEN_GRAPH; for (std::size_t worker = 0U; worker < netw1.numWorkers_; ++worker) { - for (std::size_t channel = netw1.vertexPointer_[worker]; channel < netw1.vertexPointer_[worker + 1U]; - ++channel) { + for (std::size_t channel = netw1.vertexPointer_[worker]; channel < netw1.vertexPointer_[worker + 1U]; ++channel) { EXPECT_EQ(netw1.source(channel), worker); EXPECT_EQ(netw1.target(channel), netw1.edgeTargets_[channel]); } @@ -406,8 +405,7 @@ TEST(QNetworkTest, SrcTgt) { constexpr auto netw2 = FULLY_CONNECTED_GRAPH<9U>(); for (std::size_t worker = 0U; worker < netw2.numWorkers_; ++worker) { - for (std::size_t channel = netw2.vertexPointer_[worker]; channel < netw2.vertexPointer_[worker + 1U]; - ++channel) { + for (std::size_t channel = netw2.vertexPointer_[worker]; channel < netw2.vertexPointer_[worker + 1U]; ++channel) { EXPECT_EQ(netw2.source(channel), worker); if (channel % 9U == 0U) { EXPECT_EQ(netw2.target(channel), worker); @@ -423,3 +421,51 @@ TEST(QNetworkTest, PrintQNetwork) { constexpr QNetwork<10, 30> netw = PETERSEN_GRAPH; netw.printQNetwork(); } + +TEST(QNetworkTest, WorkLoads) { + constexpr auto netw1 = FULLY_CONNECTED_GRAPH<1U>(); + std::array expectedLoad1; + for (double &val : expectedLoad1) { val = 1.0 / static_cast(netw1.numWorkers_); } + + const auto load1 = workLoadDistribution(netw1); + for (std::size_t worker = 0U; worker < netw1.numWorkers_; ++worker) { + EXPECT_DOUBLE_EQ(load1[worker], expectedLoad1[worker]); + } + + constexpr auto netw3 = FULLY_CONNECTED_GRAPH<3U>(); + std::array expectedLoad3; + for (double &val : expectedLoad3) { val = 1.0 / static_cast(netw3.numWorkers_); } + + const auto load3 = workLoadDistribution(netw3); + for (std::size_t worker = 0U; worker < netw3.numWorkers_; ++worker) { + EXPECT_DOUBLE_EQ(load3[worker], expectedLoad3[worker]); + } + + constexpr auto netw12 = FULLY_CONNECTED_GRAPH<12U>(); + std::array expectedLoad12; + for (double &val : expectedLoad12) { val = 1.0 / static_cast(netw12.numWorkers_); } + + const auto load12 = workLoadDistribution(netw12); + for (std::size_t worker = 0U; worker < netw12.numWorkers_; ++worker) { + EXPECT_DOUBLE_EQ(load12[worker], expectedLoad12[worker]); + } + + constexpr auto netw10 = PETERSEN_GRAPH; + std::array expectedLoad10; + for (double &val : expectedLoad10) { val = 1.0 / static_cast(netw10.numWorkers_); } + + const auto load10 = workLoadDistribution(netw10); + for (std::size_t worker = 0U; worker < netw10.numWorkers_; ++worker) { + EXPECT_DOUBLE_EQ(load10[worker], expectedLoad10[worker]); + } + + constexpr auto netw = QNetwork<4U, 10U>( + {0, 2, 4, 7, 10}, {0, 1, 2, 3, 0, 2, 3, 0, 2, 3}, {0, 1, 2, 3}, {1, 1, 1, 1, 1, 2, 2, 1, 2, 2} + ); + std::array expectedLoad = {1.0 / 4.0, 1.0 / 8.0, 5.0 / 16.0, 5.0 / 16.0}; + + const auto load = workLoadDistribution(netw); + for (std::size_t worker = 0U; worker < netw.numWorkers_; ++worker) { + EXPECT_NEAR(load[worker], expectedLoad[worker], 1e-8); + } +} From 24e969f8dcaf5bad805f73e2587d163a17296645 Mon Sep 17 00:00:00 2001 From: Raphael Steiner Date: Sun, 29 Mar 2026 19:22:55 +0200 Subject: [PATCH 3/8] fixed type / merge --- .../Drawing/WorkLoadDistribution.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename include/{ParallelPriotityQueue => ParallelPriorityQueue}/Drawing/WorkLoadDistribution.hpp (98%) diff --git a/include/ParallelPriotityQueue/Drawing/WorkLoadDistribution.hpp b/include/ParallelPriorityQueue/Drawing/WorkLoadDistribution.hpp similarity index 98% rename from include/ParallelPriotityQueue/Drawing/WorkLoadDistribution.hpp rename to include/ParallelPriorityQueue/Drawing/WorkLoadDistribution.hpp index 8dffe05..8d9ffc2 100644 --- a/include/ParallelPriotityQueue/Drawing/WorkLoadDistribution.hpp +++ b/include/ParallelPriorityQueue/Drawing/WorkLoadDistribution.hpp @@ -21,7 +21,7 @@ limitations under the License. #include #include -#include "ParallelPriotityQueue/QNetwork.hpp" +#include "ParallelPriorityQueue/QNetwork.hpp" namespace spapq { From 62f138dc98141e48bd6f29d35bd48afee16188ff Mon Sep 17 00:00:00 2001 From: Raphael Steiner Date: Sun, 29 Mar 2026 20:05:20 +0200 Subject: [PATCH 4/8] dot writer --- .../Drawing/QNetworkToDot.hpp | 124 ++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 include/ParallelPriorityQueue/Drawing/QNetworkToDot.hpp diff --git a/include/ParallelPriorityQueue/Drawing/QNetworkToDot.hpp b/include/ParallelPriorityQueue/Drawing/QNetworkToDot.hpp new file mode 100644 index 0000000..f7261d0 --- /dev/null +++ b/include/ParallelPriorityQueue/Drawing/QNetworkToDot.hpp @@ -0,0 +1,124 @@ +/* +Copyright 2026 Raphael S. Steiner + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +@author Raphael S. Steiner +*/ + +#pragma once + +#include +#include +#include +#include + +#include "ParallelPriorityQueue/Drawing/WorkLoadDistribution.hpp" +#include "ParallelPriorityQueue/QNetwork.hpp" + +namespace spapq { + +template +void globalQNetworkInfo(const QNetwork &netw, std::ostream &os) { + os << " subgraph Info{\n"; + os << " NetworkInfo [\n"; + os << " label=<\n"; + os << " \n"; + os << " \n"; + os << " \n"; + os << "
QNetwork Information
\n"; + os << " \n"; + os << " \n"; + os << " \n"; + os << " \n"; + os << " \n"; + os << "
Number of Workers" << netw.numWorkers_ << "
Number of Channels" << netw.numChannels_ << "
Buffer Size" << netw.channelBufferSize_ << "
Enqueue Frequency" << netw.enqueueFrequency_ << "
Max. Push Attempts" << netw.maxPushAttempts_ << "
\n"; + os << " >\n"; + os << " ];\n"; + os << " }\n\n"; +} + +template +void QNetworkWorkerInfo(const QNetwork &netw, const std::array &loads, const std::size_t worker, std::ostream &os) { + os << " Worker" << worker << " [\n"; + os << " label=<\n"; + os << " \n"; + os << " \n"; + os << " \n"; + os << " \n"; + os << "
Worker " << worker << "
Core" << netw.logicalCore_[worker] << "
Load" << loads[worker] << "
\n"; + os << " >\n"; + os << " ];\n\n"; +} + +template +void QNetworkChannelInfo(const QNetwork &netw, const std::size_t edge, std::ostream &os) { + const std::size_t source = netw.source(edge); + const std::size_t target = netw.target(edge); + + os << " Worker" << source << " -> Worker" << target << " [\n"; + os << " label=<\n"; + os << " \n"; + os << " \n"; + os << " \n"; + os << "
Mult." << netw.multiplicities_[edge] << "
Batch" << netw.batchSize_[edge] << "
\n"; + os << " >\n"; + os << " ];\n"; +} + +template +void QNetworkToDot(const QNetwork &netw, std::ostream &os) { + if (!os.is_open()) { + std::cerr << "Failed to open file to write QNetwork dot!" << std::endl; + return; + } + + const std::array loads = workLoadDistribution(netw); + + // Header + os << std::fixed << std::setprecision(2); + os << "digraph QNetwork{\n"; + os << " node [shape=plaintext;]\n"; + os << " edge [shape=plaintext; arrowhead=\"vee\"; fontsize=\"8\";]\n\n"; + + // Global Network Info + globalQNetworkInfo(netw, os); + + // Actual Network + os << " subgraph cluster_network{\n"; + os << " label=\"QNetwork\";\n"; + os << " margin=\"30\";\n\n"; + + // Workers (Vertices) + for (std::size_t worker = 0U; worker < workers; ++worker) { + QNetworkWorkerInfo(netw, loads, worker, os); + } + + // Channels (Edges) + for (std::size_t worker = 0U; worker < workers; ++worker) { + for (std::size_t edge = netw.vertexPointer_[worker]; edge < netw.vertexPointer_[worker + 1U]; ++edge) { + QNetworkChannelInfo(netw, edge, os); + } + } + + os << " }\n"; + os << "}\n"; +} + +template +void QNetworkToDot(const QNetwork &netw, const std::string &filename) { + std::ofstream os(filename); + WriteTxt(netw, os); +} + +} // namespace spapq From f5a5621e0bd463c75f36fcd31c0d89e07f45fb6d Mon Sep 17 00:00:00 2001 From: Raphael Steiner Date: Sun, 29 Mar 2026 20:34:29 +0200 Subject: [PATCH 5/8] Visualiser First Version --- CMakeLists.txt | 2 + apps/CMakeLists.txt | 35 +++++++++++++++++ apps/QNetworkDotWriter.cpp | 39 +++++++++++++++++++ .../Drawing/QNetworkToDot.hpp | 6 +-- 4 files changed, 77 insertions(+), 5 deletions(-) create mode 100644 apps/CMakeLists.txt create mode 100644 apps/QNetworkDotWriter.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 547d93a..b8b9aa4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -137,6 +137,8 @@ else() message(STATUS "Benchmarks will not be built (BUILD_BENCHMARK is OFF).") endif() +add_subdirectory(apps) + # --- Documentation Generation --- # Add a custom target to build Doxygen documentation find_package(Doxygen QUIET) diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt new file mode 100644 index 0000000..0ef9e8f --- /dev/null +++ b/apps/CMakeLists.txt @@ -0,0 +1,35 @@ +# Copyright 2026 Raphael S. Steiner +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +cmake_minimum_required(VERSION 3.20) + +# Create an empty list for the applications +set( App_list ) + +# Function to create an application +macro( _add_App name ) + # Add the application to the list + list( APPEND App_list ${name} ) + + # Create the Benchmark + add_executable(${name} ${name}.cpp) + target_link_libraries(${name} PRIVATE SPAPQueue ProjectExecutableFlags) + target_include_directories(${name} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include) +endmacro() + +# Adding Applications +_add_App( QNetworkDotWriter ) + +# Custom target to compile all the Benchmarks +add_custom_target( build_Apps DEPENDS ${App_list} ) \ No newline at end of file diff --git a/apps/QNetworkDotWriter.cpp b/apps/QNetworkDotWriter.cpp new file mode 100644 index 0000000..4aa9356 --- /dev/null +++ b/apps/QNetworkDotWriter.cpp @@ -0,0 +1,39 @@ +/* +Copyright 2025 Raphael S. Steiner + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +@author Raphael S. Steiner +*/ + +#include + +#include "ParallelPriorityQueue/Drawing/QNetworkToDot.hpp" +#include "ParallelPriorityQueue/GraphExamples/PetersenGraph.hpp" + +using namespace spapq; + +int main(int argc, char *argv[]) { + if (argc < 2) { + std::cout << "Usage:\n" + << " " << argv[0] << " \n"; + return 1; + } + + std::ofstream os(argv[1]); + + constexpr auto netw = PETERSEN_GRAPH; + + QNetworkToDot(netw, os); + return 0; +} diff --git a/include/ParallelPriorityQueue/Drawing/QNetworkToDot.hpp b/include/ParallelPriorityQueue/Drawing/QNetworkToDot.hpp index f7261d0..b818afd 100644 --- a/include/ParallelPriorityQueue/Drawing/QNetworkToDot.hpp +++ b/include/ParallelPriorityQueue/Drawing/QNetworkToDot.hpp @@ -78,11 +78,6 @@ void QNetworkChannelInfo(const QNetwork &netw, const std::siz template void QNetworkToDot(const QNetwork &netw, std::ostream &os) { - if (!os.is_open()) { - std::cerr << "Failed to open file to write QNetwork dot!" << std::endl; - return; - } - const std::array loads = workLoadDistribution(netw); // Header @@ -90,6 +85,7 @@ void QNetworkToDot(const QNetwork &netw, std::ostream &os) { os << "digraph QNetwork{\n"; os << " node [shape=plaintext;]\n"; os << " edge [shape=plaintext; arrowhead=\"vee\"; fontsize=\"8\";]\n\n"; + os << " rankdir=LR"; // Global Network Info globalQNetworkInfo(netw, os); From 89fbc2a4ba81e2a9c8414dd07531aeb795e15286 Mon Sep 17 00:00:00 2001 From: Raphael Steiner Date: Sun, 29 Mar 2026 20:37:46 +0200 Subject: [PATCH 6/8] small fix --- include/ParallelPriorityQueue/Drawing/QNetworkToDot.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/ParallelPriorityQueue/Drawing/QNetworkToDot.hpp b/include/ParallelPriorityQueue/Drawing/QNetworkToDot.hpp index b818afd..66dda40 100644 --- a/include/ParallelPriorityQueue/Drawing/QNetworkToDot.hpp +++ b/include/ParallelPriorityQueue/Drawing/QNetworkToDot.hpp @@ -84,8 +84,8 @@ void QNetworkToDot(const QNetwork &netw, std::ostream &os) { os << std::fixed << std::setprecision(2); os << "digraph QNetwork{\n"; os << " node [shape=plaintext;]\n"; - os << " edge [shape=plaintext; arrowhead=\"vee\"; fontsize=\"8\";]\n\n"; - os << " rankdir=LR"; + os << " edge [shape=plaintext; arrowhead=\"vee\"; fontsize=\"8\";]\n"; + os << " rankdir=LR\n\n"; // Global Network Info globalQNetworkInfo(netw, os); From 5829d5a1d892eb4ac41784f65fdfe647b282f837 Mon Sep 17 00:00:00 2001 From: Raphael Steiner Date: Tue, 31 Mar 2026 06:28:24 +0200 Subject: [PATCH 7/8] Visualiser second version --- GarphExample.dot | 138 ------------------ apps/QNetworkDotWriter.cpp | 4 +- .../Drawing/QNetworkToDot.hpp | 18 +-- 3 files changed, 11 insertions(+), 149 deletions(-) delete mode 100644 GarphExample.dot diff --git a/GarphExample.dot b/GarphExample.dot deleted file mode 100644 index 9c7a56b..0000000 --- a/GarphExample.dot +++ /dev/null @@ -1,138 +0,0 @@ -digraph QNetwork{ - node [shape=plaintext;] - edge [shape=plaintext; arrowhead="vee"; fontsize="8";] - - subgraph Info{ - layer="0"; - - NetworkInfo [ - label=< - - - -
QNetwork Information
- - - - - -
Number of Workers4
Number of Channels4
Buffer Size16
Enqueue Frequency8
Max. Push Attempts8
- > - ]; - } - - subgraph cluster_network{ - label="QNetwork"; - layer="1"; - margin="30"; - - Worker0 [ - label=< - - - - -
Worker 0
Core0
Load0.25
- > - ]; - - Worker1 [ - label=< - - - - -
Worker 1
Core1
Load0.25
- > - ]; - - Worker2 [ - label=< - - - - -
Worker 2
Core2
Load0.25
- > - ]; - - Worker3 [ - label=< - - - - -
Worker 3
Core3
Load0.25
- > - ]; - - Worker0 -> Worker0 [ - label=< - - - -
Mult.1
Batch4
- > - ]; - Worker0 -> Worker1 [ - label=< - - - -
Mult.1
Batch4
- > - ]; - - Worker1 -> Worker2 [ - label=< - - - -
Mult.1
Batch8
- > - ]; - Worker1 -> Worker3 [ - label=< - - - -
Mult.1
Batch8
- > - ]; - - Worker2 -> Worker2 [ - label=< - - - -
Mult.1
Batch4
- > - ]; - Worker2 -> Worker3 [ - label=< - - - -
Mult.1
Batch4
- > - ]; - - Worker3 -> Worker0 [ - label=< - - - -
Mult.1
Batch8
- > - ]; - Worker3 -> Worker1 [ - label=< - - - -
Mult.1
Batch8
- > - ]; - - } -} \ No newline at end of file diff --git a/apps/QNetworkDotWriter.cpp b/apps/QNetworkDotWriter.cpp index 4aa9356..c3f5e59 100644 --- a/apps/QNetworkDotWriter.cpp +++ b/apps/QNetworkDotWriter.cpp @@ -19,6 +19,8 @@ limitations under the License. #include #include "ParallelPriorityQueue/Drawing/QNetworkToDot.hpp" +#include "ParallelPriorityQueue/GraphExamples/FullyConnectedGraph.hpp" +#include "ParallelPriorityQueue/GraphExamples/LineGraph.hpp" #include "ParallelPriorityQueue/GraphExamples/PetersenGraph.hpp" using namespace spapq; @@ -32,7 +34,7 @@ int main(int argc, char *argv[]) { std::ofstream os(argv[1]); - constexpr auto netw = PETERSEN_GRAPH; + constexpr auto netw = LINE_GRAPH(FULLY_CONNECTED_GRAPH<3U>()); QNetworkToDot(netw, os); return 0; diff --git a/include/ParallelPriorityQueue/Drawing/QNetworkToDot.hpp b/include/ParallelPriorityQueue/Drawing/QNetworkToDot.hpp index 66dda40..8af6e0f 100644 --- a/include/ParallelPriorityQueue/Drawing/QNetworkToDot.hpp +++ b/include/ParallelPriorityQueue/Drawing/QNetworkToDot.hpp @@ -30,7 +30,6 @@ namespace spapq { template void globalQNetworkInfo(const QNetwork &netw, std::ostream &os) { - os << " subgraph Info{\n"; os << " NetworkInfo [\n"; os << " label=<\n"; os << " \n"; @@ -44,8 +43,7 @@ void globalQNetworkInfo(const QNetwork &netw, std::ostream &o os << "
\n"; os << " \n"; os << " >\n"; - os << " ];\n"; - os << " }\n\n"; + os << " ];\n\n"; } template @@ -55,7 +53,7 @@ void QNetworkWorkerInfo(const QNetwork &netw, const std::arra os << " \n"; os << " \n"; os << " \n"; - os << " \n"; + os << " \n"; os << "
Worker " << worker << "
Core" << netw.logicalCore_[worker] << "
Load" << loads[worker] << "
Load" << loads[worker] * 100.0 << "%
\n"; os << " >\n"; os << " ];\n\n"; @@ -81,8 +79,13 @@ void QNetworkToDot(const QNetwork &netw, std::ostream &os) { const std::array loads = workLoadDistribution(netw); // Header - os << std::fixed << std::setprecision(2); + os << std::fixed << std::setprecision(1); os << "digraph QNetwork{\n"; + os << " layout=\"fdp\";\n"; + os << " len=\"2.0\";\n"; + os << " sep=\"+45\";\n"; + os << " dim=3;\n\n"; + os << " node [shape=plaintext;]\n"; os << " edge [shape=plaintext; arrowhead=\"vee\"; fontsize=\"8\";]\n"; os << " rankdir=LR\n\n"; @@ -91,10 +94,6 @@ void QNetworkToDot(const QNetwork &netw, std::ostream &os) { globalQNetworkInfo(netw, os); // Actual Network - os << " subgraph cluster_network{\n"; - os << " label=\"QNetwork\";\n"; - os << " margin=\"30\";\n\n"; - // Workers (Vertices) for (std::size_t worker = 0U; worker < workers; ++worker) { QNetworkWorkerInfo(netw, loads, worker, os); @@ -107,7 +106,6 @@ void QNetworkToDot(const QNetwork &netw, std::ostream &os) { } } - os << " }\n"; os << "}\n"; } From 725c9c65f4da678e9259eb2d42a8e567cb83e2b5 Mon Sep 17 00:00:00 2001 From: Raphael Steiner Date: Wed, 1 Apr 2026 07:15:35 +0200 Subject: [PATCH 8/8] small fixes --- apps/QNetworkDotWriter.cpp | 2 +- include/ParallelPriorityQueue/Drawing/QNetworkToDot.hpp | 6 ++---- .../ParallelPriorityQueue/Drawing/WorkLoadDistribution.hpp | 3 +-- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/apps/QNetworkDotWriter.cpp b/apps/QNetworkDotWriter.cpp index c3f5e59..c653f29 100644 --- a/apps/QNetworkDotWriter.cpp +++ b/apps/QNetworkDotWriter.cpp @@ -1,5 +1,5 @@ /* -Copyright 2025 Raphael S. Steiner +Copyright 2026 Raphael S. Steiner Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/include/ParallelPriorityQueue/Drawing/QNetworkToDot.hpp b/include/ParallelPriorityQueue/Drawing/QNetworkToDot.hpp index 8af6e0f..c8107c1 100644 --- a/include/ParallelPriorityQueue/Drawing/QNetworkToDot.hpp +++ b/include/ParallelPriorityQueue/Drawing/QNetworkToDot.hpp @@ -100,10 +100,8 @@ void QNetworkToDot(const QNetwork &netw, std::ostream &os) { } // Channels (Edges) - for (std::size_t worker = 0U; worker < workers; ++worker) { - for (std::size_t edge = netw.vertexPointer_[worker]; edge < netw.vertexPointer_[worker + 1U]; ++edge) { - QNetworkChannelInfo(netw, edge, os); - } + for (std::size_t edge = 0U; edge < channels; ++edge) { + QNetworkChannelInfo(netw, edge, os); } os << "}\n"; diff --git a/include/ParallelPriorityQueue/Drawing/WorkLoadDistribution.hpp b/include/ParallelPriorityQueue/Drawing/WorkLoadDistribution.hpp index 8d9ffc2..7dfa4c6 100644 --- a/include/ParallelPriorityQueue/Drawing/WorkLoadDistribution.hpp +++ b/include/ParallelPriorityQueue/Drawing/WorkLoadDistribution.hpp @@ -26,7 +26,7 @@ limitations under the License. namespace spapq { template -std::array workLoadDistribution(const QNetwork &netw) { +std::array workLoadDistribution(const QNetwork &netw, const double epsilon = 1e-10) { assert(netw.isValidQNetwork()); assert(netw.isStronglyConnected()); @@ -59,7 +59,6 @@ std::array workLoadDistribution(const QNetwork(workers); } std::array distAfterIteration; - constexpr double epsilon = 1e-10; bool loop = true; while (loop) { loop = false;