Skip to content

Commit c8bc418

Browse files
committed
added multithreaded none-MRNG edge removal +publish
1 parent 5e6a075 commit c8bc418

File tree

3 files changed

+69
-53
lines changed

3 files changed

+69
-53
lines changed

cpp/deglib/include/analysis.h

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
#pragma once
22

33
#include <math.h>
4+
#include <thread>
45
#include <algorithm>
56

7+
#include "concurrent.h"
68
#include "search.h"
79
#include "graph.h"
810

@@ -165,12 +167,12 @@ namespace deglib::analysis
165167

166168
static uint32_t calc_non_rng_edges(const deglib::graph::MutableGraph& graph) {
167169
const auto vertex_count = graph.size();
168-
const auto edge_per_vertex =graph.getEdgesPerVertex();
169-
170-
uint32_t removed_rng_edges = 0;
171-
for (uint32_t i = 0; i < vertex_count; i++) {
172-
const auto vertex_index = i;
170+
const auto edge_per_vertex = graph.getEdgesPerVertex();
173171

172+
const auto thread_count = std::thread::hardware_concurrency();
173+
auto removed_rng_edges_per_thread = std::vector<uint32_t>(thread_count);
174+
deglib::concurrent::parallel_for(0, vertex_count, thread_count, [&] (size_t vertex_index, size_t thread_id) {
175+
uint32_t removed_rng_edges = 0;
174176
const auto neighbor_indices = graph.getNeighborIndices(vertex_index);
175177
const auto neighbor_weights = graph.getNeighborWeights(vertex_index);
176178

@@ -182,7 +184,13 @@ namespace deglib::analysis
182184
if(checkRNG(graph, edge_per_vertex, vertex_index, neighbor_index, neighbor_weight) == false)
183185
removed_rng_edges++;
184186
}
185-
}
187+
removed_rng_edges_per_thread[thread_id] += removed_rng_edges;
188+
});
189+
190+
// aggregate
191+
uint32_t removed_rng_edges = 0;
192+
for (uint32_t i = 0; i < thread_count; i++)
193+
removed_rng_edges += removed_rng_edges_per_thread[i];
186194

187195
return removed_rng_edges;
188196
}

cpp/deglib/include/builder.h

Lines changed: 54 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1361,34 +1361,42 @@ class EvenRegularGraphBuilder {
13611361
*/
13621362
void remove_non_mrng_edges(deglib::graph::MutableGraph& graph) {
13631363

1364-
const auto vertex_count = graph.size();
1365-
const auto edge_per_vertex = graph.getEdgesPerVertex();
1364+
const auto vertex_count = graph.size();
1365+
const auto edge_per_vertex = graph.getEdgesPerVertex();
13661366

1367-
const auto start = std::chrono::steady_clock::now();
1367+
const auto start = std::chrono::steady_clock::now();
1368+
const auto thread_count = std::thread::hardware_concurrency();
1369+
auto removed_rng_edges_per_thread = std::vector<uint32_t>(thread_count);
1370+
deglib::concurrent::parallel_for(0, vertex_count, thread_count, [&] (size_t vertex_index, size_t thread_id) {
13681371
uint32_t removed_rng_edges = 0;
1369-
for (uint32_t i = 0; i < vertex_count; i++) {
1370-
const auto vertex_index = i;
13711372

1372-
const auto neighbor_indices = graph.getNeighborIndices(vertex_index);
1373-
const auto neighbor_weights = graph.getNeighborWeights(vertex_index);
1373+
const auto neighbor_indices = graph.getNeighborIndices(vertex_index);
1374+
const auto neighbor_weights = graph.getNeighborWeights(vertex_index);
13741375

1375-
// find all none rng conform neighbors
1376-
std::vector<uint32_t> remove_neighbor_ids;
1377-
for (uint32_t n = 0; n < edge_per_vertex; n++) {
1378-
const auto neighbor_index = neighbor_indices[n];
1379-
const auto neighbor_weight = neighbor_weights[n];
1376+
// find all none rng conform neighbors
1377+
std::vector<uint32_t> remove_neighbor_ids;
1378+
for (uint32_t n = 0; n < edge_per_vertex; n++) {
1379+
const auto neighbor_index = neighbor_indices[n];
1380+
const auto neighbor_weight = neighbor_weights[n];
13801381

1381-
if(deglib::analysis::checkRNG(graph, edge_per_vertex, vertex_index, neighbor_index, neighbor_weight) == false) {
1382-
remove_neighbor_ids.emplace_back(neighbor_index);
1383-
}
1384-
}
1382+
if(deglib::analysis::checkRNG(graph, edge_per_vertex, vertex_index, neighbor_index, neighbor_weight) == false) {
1383+
remove_neighbor_ids.emplace_back(neighbor_index);
1384+
}
1385+
}
13851386

1386-
for (uint32_t n = 0; n < remove_neighbor_ids.size(); n++) {
1387-
graph.changeEdge(vertex_index, remove_neighbor_ids[n], vertex_index, 0);
1388-
removed_rng_edges++;
1389-
}
1387+
for (uint32_t n = 0; n < remove_neighbor_ids.size(); n++) {
1388+
graph.changeEdge(vertex_index, remove_neighbor_ids[n], vertex_index, 0);
1389+
removed_rng_edges++;
13901390
}
1391-
const auto duration_ms = uint32_t(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start).count());
1391+
removed_rng_edges_per_thread[thread_id] += removed_rng_edges;
1392+
});
1393+
1394+
// aggregate
1395+
uint32_t removed_rng_edges = 0;
1396+
for (uint32_t i = 0; i < thread_count; i++)
1397+
removed_rng_edges += removed_rng_edges_per_thread[i];
1398+
1399+
const auto duration_ms = uint32_t(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start).count());
13921400

13931401
std::cout << "Removed " << removed_rng_edges << " edges in " << duration_ms << " ms. Final graph contains " << deglib::analysis::calc_non_rng_edges(graph) << " non-RNG edges\n";
13941402
}
@@ -1399,35 +1407,35 @@ void remove_non_mrng_edges(deglib::graph::MutableGraph& graph) {
13991407
*/
14001408
void optimze_edges(deglib::graph::MutableGraph& graph, const uint8_t k_opt, const float eps_opt, const uint8_t i_opt, const uint32_t iterations) {
14011409

1402-
auto rnd = std::mt19937(7); // default 7
1410+
auto rnd = std::mt19937(7); // default 7
14031411

1404-
// create a graph builder to add vertices to the new graph and improve its edges
1412+
// create a graph builder to add vertices to the new graph and improve its edges
14051413
std::cout << "Start graph builder\n";
1406-
auto builder = deglib::builder::EvenRegularGraphBuilder(graph, rnd, deglib::builder::Unknown, 0, 0.0f, k_opt, eps_opt, i_opt, 1, 0);
1407-
1408-
// check the integrity of the graph during the graph build process
1409-
auto start = std::chrono::steady_clock::now();
1410-
uint64_t duration_ms = 0;
1411-
const auto improvement_callback = [&](deglib::builder::BuilderStatus& status) {
1412-
const auto size = graph.size();
1413-
1414-
if(status.step % (iterations/10) == 0) {
1415-
duration_ms += uint32_t(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start).count());
1416-
auto avg_edge_weight = deglib::analysis::calc_avg_edge_weight(graph, 100);
1417-
auto valid_weights = deglib::analysis::check_graph_weights(graph) && deglib::analysis::check_graph_regularity(graph, uint32_t(size), true);
1418-
auto connected = deglib::analysis::check_graph_connectivity(graph);
1419-
1420-
auto duration = duration_ms / 1000;
1421-
std::cout << std::setw(7) << status.step << " step, " << std::setw(5) << duration << "s, AEW: " << std::fixed << std::setprecision(2) << std::setw(4) << avg_edge_weight << ", " << (connected ? "" : "not") << " connected, " << (valid_weights ? "valid" : "invalid") << "\n";
1422-
start = std::chrono::steady_clock::now();
1423-
}
1414+
auto builder = deglib::builder::EvenRegularGraphBuilder(graph, rnd, deglib::builder::Unknown, 0, 0.0f, k_opt, eps_opt, i_opt, 1, 0);
1415+
1416+
// check the integrity of the graph during the graph build process
1417+
auto start = std::chrono::steady_clock::now();
1418+
uint64_t duration_ms = 0;
1419+
const auto improvement_callback = [&](deglib::builder::BuilderStatus& status) {
1420+
const auto size = graph.size();
1421+
1422+
if(status.step % (iterations/10) == 0) {
1423+
duration_ms += uint32_t(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start).count());
1424+
auto avg_edge_weight = deglib::analysis::calc_avg_edge_weight(graph, 100);
1425+
auto valid_weights = deglib::analysis::check_graph_weights(graph) && deglib::analysis::check_graph_regularity(graph, uint32_t(size), true);
1426+
auto connected = deglib::analysis::check_graph_connectivity(graph);
1427+
1428+
auto duration = duration_ms / 1000;
1429+
std::cout << std::setw(7) << status.step << " step, " << std::setw(5) << duration << "s, AEW: " << std::fixed << std::setprecision(2) << std::setw(4) << avg_edge_weight << ", " << (connected ? "" : "not") << " connected, " << (valid_weights ? "valid" : "invalid") << "\n";
1430+
start = std::chrono::steady_clock::now();
1431+
}
14241432

1425-
if(status.step > iterations)
1426-
builder.stop();
1427-
};
1433+
if(status.step > iterations)
1434+
builder.stop();
1435+
};
14281436

1429-
// start the build process
1430-
builder.build(improvement_callback, true);
1437+
// start the build process
1438+
builder.build(improvement_callback, true);
14311439
}
14321440

14331441
} // end namespace deglib::builder

python/src/deglib/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from .distances import Metric, FloatSpace
1111

1212

13-
__version__ = "0.1.53"
13+
__version__ = "0.1.54"
1414

1515

1616
__all__ = [

0 commit comments

Comments
 (0)