BGL のほとんどすべてのグラフ アルゴリズムでは、マッピングが必要です: vertex -> int は、各頂点に範囲 [0, num_vertices(g) ) 内の一意の整数を割り当てます。このマッピングは「頂点インデックス」として知られており、通常はプロパティマップとしてアクセスできます。
そうは言っても、頂点はすでに整数であるか、いくつかの整数に関連付けられていると想定できます(たとえば、unordered_mapには「mapped_type」に追加のフィールドがあります)。入力頂点が std::vector などの連続したタイトな配列に格納されている場合は、(パフォーマンスとメモリの点で) さらに優れており、インデックス付けは自然です。
頂点が[関連付けられた]整数である場合、メモリ不足のグラフの最適な選択は「圧縮されたスパース行グラフ」です。グラフは不変であるため、グラフを生成する前にエッジ コンテナーを設定する必要があります。
ravenspoint が説明したように、最良の選択は、各スレッドに独自の結果のローカル コンテナーを装備し、ローカル結果を最終結果にマージするときにのみ中央コンテナーをロックすることです。このような戦略は、TBB テンプレートtbb::parallel_reduceによってロックレスで実装されます。したがって、グラフ構築の完全なコードは、おおよそ次のようになります。
#include "tbb/blocked_range2d.h"
#include "tbb/parallel_reduce.h"
#include "boost/graph/compressed_sparse_row_graph.hpp"
typedef something vertex; //e.g.something is integer giving index of a real data
class EdgeBuilder
{
public:
typedef std::pair<int,int> edge;
typedef std::vector<edge> Edges;
typedef ActualStorage Input;
EdgeBuilder(const Input & input):_input(input){} //OPTIONAL: reserve some space in _edges
EdgeBuilder( EdgeBuilder& parent, tbb::split ): _input(parent.input){} // reserve something
void operator()( const const tbb::blocked_range2d<size_t>& r )
{
for( size_t i=r.rows().begin(); i!=r.rows().end(); ++i ){
for( size_t j=r.cols().begin(); j!=r.cols().end(); ++j ) {
//I assume you provide some function to compute existence
if (my_func_edge_exist(_input,i, j))
m_edges.push_back(edge(i,j));
}
}
}
//merges local results from two TBB threads
void join( EdgeBuilder& rhs )
{
m_edges.insert( m_edges.end(), rhs.m_edges.begin(), rhs.m_edges.end() );
}
Edges _edges; //for a given interval of vertices
const Input & _input;
};
//full flow:
boost::compressed_sparse_row_graph<>* build_graph( const Storage & vertices)
{
EdgeBuilder builder(vertices);
tbb::blocked_range2d<size_t,size_t> range(0,vertices.size(), 100, //row grain size
0,vertices.size(), 100); //col grain size
tbb::parallel_reduce(range, builder);
boost::compressed_sparse_row_graph<>
theGraph = new boost::compressed_sparse_row_graph<>
(boost::edges_are_unsorted_multi_pass_t,
builder._edges.begin(), builder._edges.end(),
vertices.size() );
return theGraph;
}