Pregel的C++ API
一、定点类
Pregel已经预先定义好一个基类——Vertex类:
template <typename VertexValue, typename EdgeValue, typename MessageValue>
class Vertex {
public:
virtual void Compute(MessageIterator* msgs) = 0; //每个顶点的计算函数
const string& vertex_id() const; //顶点id
int64 superstep() const; //当前执行的超步数
const VertexValue& GetValue(); //获取顶点的关联值
VertexValue* MutableValue(); //修改顶点的关联值
OutEdgeIterator GetOutEdgeIterator(); //获取当前顶点的所有出射边对象
void SendMessageTo(const string& dest_vertex, const MessageValue& message); //沿着出射边发送消息到目标顶点
void VoteToHalt(); //设置顶点状态为非活跃
};
在Vetex类中,定义了三个值类型参数,分别表示顶点、边和消息。每一个顶点都有一个给定类型的值与之对应
编写Pregel程序时,需要继承Vertex类,并且覆写Vertex类的虚函数Compute()
(1)在Pregel执行计算过程时,在每个超步中都会并行调用每个顶点上定义的Compute()函数
(2)允许Compute()方法查询当前顶点及其边的信息,以及发送消息到其他的顶点
(3)Compute()方法可以调用GetValue()方法来获取当前顶点的值
(4)调用MutableValue()方法来修改当前顶点的值
(5)通过由出射边的迭代器提供的方法来查看、修改出射边对应的值
(6)对状态的修改,对于被修改的顶点而言是可以立即被看见的,但是,对于其他顶点而言是不可见的(当前超步中当前顶点状态变化其他顶点在当前超步中看不到),因此,不同顶点并发进行的数据访问是不存在竞争关系的
整个过程中,唯一需要在超步之间持久化(数据存储在稳定的存储器中,如硬盘)的顶点级状态,是顶点和其对应的边所关联的值,因而,Pregel计算框架所需要管理的图状态就只包括顶点和边所关联的值,这种做法大大简化了计算流程,同时,也有利于图的分布和故障恢复
二、消息传递机制
1、顶点之间的通讯是借助于消息传递机制来实现的,每条消息都包含了消息值和需要到达的目标顶点ID。用户可以通过Vertex类的模板参数来设定消息值的数据类型
2、在一个超步S中,一个顶点可以发送任意数量的消息,这些消息将在下一个超步(S+1)中被其他顶点接收
3、也就是说,在超步(S+1)中,当Pregel计算框架在顶点V上执行用户自定义的Compute()方法时,所有在前一个超步S中发送给顶点V的消息,都可以通过一个迭代器来访问到。迭代器不能保证消息的顺序,不过可以保证消息一定会被传送并且不会被重复传送
4、一个顶点V通过与之关联的出射边向外发送消息,并且,消息要到达的目标顶点并不一定是与顶点V相邻的顶点,一个消息可以连续经过多条连通的边到达某个与顶点V不相邻的顶点U,U可以从接收的消息中获取到与其不相邻的顶点V的ID

三、Combiner合并
1、Pregel计算框架在消息发出去之前,Combiner可以将发往同一个顶点的多个整型值进行求和得到一个值,只需向外发送这个“求和结果”,从而实现了由多个消息合并成一个消息,大大减少了传输和缓存的开销
2、在默认情况下,Pregel计算框架并不会开启Combiner功能,因为,通常很难找到一种对所有顶点的Compute()函数都合适的Combiner
3、当用户打算开启Combiner功能时,可以继承Combiner类并覆写虚函数Combine()
4、此外,通常只对那些满足交换律和结合律的操作才可以去开启Combiner功能(开启后不影响开启前的执行结果),因为,Pregel计算框架无法保证哪些消息会被合并,也无法保证消息传递给 Combine()的顺序和合并操作执行的顺序

上图中是求最大值的合并Combiner例子。该例子中Combiner逻辑是取输入的最大值。这样不改变最终结果,又减少了消息数量。
四、Aggregator聚合器
1、Aggregator提供了一种全局通信、监控和数据查看的机制
2、在一个超步S中,每一个顶点都可以向一个Aggregator提供一个数据,Pregel计算框架会对这些值进行聚合操作产生一个值,在下一个超步(S+1)中,图中的所有顶点都可以看见这个值
3、Aggregator的聚合功能,允许在整型和字符串类型上执行最大值、最小值、求和操作,比如,可以定义一个“Sum”Aggregator来统计每个顶点的出射边数量,最后相加可以得到整个图的边的数量
4、Aggregator还可以实现全局协同的功能,比如,可以设计“and” Aggregator来决定在某个超步中Compute()函数是否执行某些逻辑分支,只有当“and” Aggregator显示所有顶点都满足了某条件时,才去执行这些逻辑分支
五、拓扑改变
1、Pregel计算框架允许用户在自定义函数Compute()中定义操作,修改图的拓扑结构,比如在图中增加(或删除)边或顶点
2、对于全局拓扑改变,Pregel采用了惰性协调机制,在改变请求发出时,Pregel不会对这些操作进行协调,只有当这些改变请求的消息到达目标顶点并被执行时,Pregel才会对这些操作进行协调,这样,所有针对某个顶点V的拓扑修改操作所引发的冲突,都会由V自己来处理
3、对于本地的局部拓扑改变,是不会引发冲突的,顶点或边的本地增减能够立即生效,很大程度上简化了分布式编程
六、输入和输出
在Pregel计算框架中,图的保存格式多种多样,包括文本文件、关系数据库或键值数据库等
在Pregel中,“从输入文件生成得到图结构”和“执行图计算”这两个过程是分离的,从而不会限制输入文件的格式
对于输出,Pregel也采用了灵活的方式,可以以多种方式进行输出
浙公网安备 33010602011771号