几乎BGL中的任何图形算法都需要一个映射:vertex - > int,它为范围[0,num_vertices(g))内的每个顶点分配一个唯一的整数。这种映射被称为“vertex_index”,通常可以作为property_map访问。说到这一点,我可以假设你的顶点已经是整数或者与一些整数相关联(例如你的unordered_map在“mapped_type”中有一些额外的字段)。如果您的输入顶点以连续紧密阵列存储,例如更好(对于性能和内存),例如std :: vector,那么索引是很自然的。
如果顶点与[整数]相关联,那么记忆紧密图的最佳选择是“Compressed Sparse Row Graph”。该图是不可变的,因此您需要在生成图之前填充边容器。
正如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;
}
AFAIK BGL是,将线程不安全的,如果需要,它的东西可以通过图书馆用户添加(要付出代价的其他人是太高)。这就是说,如果我记得有一个该库的并行版本(检查出来)。预分配是**总是**一件好事(即使不使用线程),但并非严格必要,您可以在循环的每次迭代中进行并行处理,然后(同步)将结果放在一起。我无法想象更多没有任何代码,但是是的......我想这是可行的。 –
我们不知道你的问题空间,但我的直觉告诉我,优化图形创建为'
N可能高达50M,K <50(通常可以是5-10)。我无法想象使它小于'O(N^2)',因为我需要在两个字符串上应用一个函数,使得'f:string x string - > unsigned int'。 (图中的每个节点表示一个字符串)任何提示,像往常一样,不只是欢迎! – senseiwa