问题
I am trying to iterate over my boost graph's vertices in parallel using OpenMP. This seems to require having an iterator that supports random access of elements (e.g., itr[i]
gets the i
th element). However, the iterator that vertices(g)
returns (a vertex_iterator
) does not seem to support this. Is there an efficient, clean way to accomplish this? Ideally, I just want a standard for loop such as this:
for (int i = 0; i < num_vertices; i++) {
vertex v = itr[i];
// Compute on vertex
}
which will cooperate with OpenMP. Thanks!
回答1:
Using a adjacency_list<..., vecS, ...>
or adjacency_matrix
would enable this by having integral-type vertex descriptors.
Thinking slightly out of the box, have a look at the Parallel Boost Graph Library (Parallel BGL). It's very likely that it does what you want (and more) but better?
Tiny Demo
Live On Coliru
Sample output (on my system):
Generated 50000000 vertices in 1879ms
Using 8 threads.
Sum of volumes for 50000000 vertices in 94ms: 2.5603e+10
Full listing:
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/random.hpp>
#include <chrono>
#include <iostream>
#include <omp.h>
#include <random>
static std::mt19937 prng { std::random_device{}() };
struct MyVertex {
uintmax_t volume = [] { static std::uniform_int_distribution<int> pick(0, 1024); return pick(prng); }();
};
using namespace boost;
using G = adjacency_list<vecS, vecS, directedS, MyVertex>;
G generate() {
using namespace std::chrono;
auto start = high_resolution_clock::now();
G g;
generate_random_graph(g, 50000000, 0, prng);
auto end = high_resolution_clock::now();
std::cerr << "Generated " << num_vertices(g) << " vertices " << "in " << duration_cast<milliseconds>(end-start).count() << "ms\n";
return g;
}
int main() {
auto const g = generate();
using namespace std::chrono;
auto start = high_resolution_clock::now();
double sum = 0;
#pragma omp parallel
{
#pragma omp single
std::cerr << "Using " << omp_get_num_threads() << " threads.\n";
#pragma omp for reduction(+:sum)
for (G::vertex_descriptor u = 0; u < num_vertices(g); ++u) {
sum += g[vertex(u, g)].volume;
}
}
auto end = high_resolution_clock::now();
std::cerr << "Sum of volumes for " << num_vertices(g) << " vertices "
<< "in " << duration_cast<milliseconds>(end-start).count() << "ms: " << sum << "\n";
}
来源:https://stackoverflow.com/questions/30135470/random-access-of-vertices-using-boostgraph