码迷,mamicode.com
首页 > 编程语言 > 详细

近似直径算法的 GraphChi 实现

时间:2015-08-25 21:42:18      阅读:177      评论:0      收藏:0      [点我收藏+]

标签:graphchi   图计算   

1. GraphChi

1.1 简介

  GraphChi 是由卡耐基梅隆大学设计, 可以在单机上进行高效大规模计算的框架, 区别于将图的信息全部存储在内存当中, GraphChi 利用单机计算机海量的硬盘进行存储, 由于硬盘与内存的访问速度差距很大, 为了弥补使用硬盘存储带来的缺陷, 他们设计出并行滑动窗口技术, 用来减少硬盘的随机读写。

1.2 并行滑动窗口技术

  将整个图谱划按照点的顺序分成不同的分片,每个分片能够完全在内存中进行
处理。 如下图所示:
技术分享

  对每个分片中的入边按照源点进行排序, 基于这种原则出边分布在所有的分片
上, 而且占据一段连续的空间。 这样对于数据的更新, 首先在内存中进行计算和
存储, 随后连续的写入其他分片中, 这样能够很好解决随机读写带来的高延迟
问题, 如下图所示。
技术分享

1.3 编程模型

  GraphChi 延续了 GraphLab 中采用的以点为中心的编程模型, 针对图谱中的节点和边都携带有用户自定义的数据。 在每一次迭代中, 同一个分片中被标记过的点并行调用update 函数进行数据更新: 获取该点入边携带的信息,出边携带的信息, 该点携带的信息,通过用户自定义的计算逻辑,对边和点携带的信息进行更新。 如下图所示:

技术分享

2. 近似直径算法: Multiple BFS

  用精确求解图的直径,需要通过从每一个点出发,进行一次 BFS 找到离该点最远的距离,最终所得值当中的最大值即为图的直径。 在图很大的情况下,这种方法带来的时间开销是无法容忍的,因此容易想到的一个方法是: 选取其中 K 个节点, 分别求出对应的最远距离,然后取最大值近似作为图的直径。

  这种想法很直观: 从 K 个节点分别做 K 次 BFS, 但是这种做法的时间开销比较大,从 K个节点出发, 有一部分点集到这 K 个节点的距离是一样的, 从另一个角度来讲, 从 K 个节点出发形成的 BFS 搜索树之间可能存在相同的路径,对于这些相同的路径其实只需一次遍历就行。因此论文中提出的方法,其实是对每个节点进行状态标记, 用 k 位的二进制数标记哪些源点出发的路径已经访问过该点, 每次迭代过程,其实是对每个节点进行状态间的转移,对于那些从源点已经经过该点的路径,不在对该点进行更新。

3. 基于 GraphChi 的 Multiple BFS 实现设计

  • K points 的选取: 选取编号为 0,1,2,4,8 …… 的点,共选取 log(nPoints)个点。
  • 点权: 用来存储该节点的状态, 从哪些源点出发的路径,已经访问过该点。
  • 边权: 将源节点的状态通过边权传递给目的节点。
  • update 函数

    • 访问该点所有的入边, 将入边的所有权值取或作为 new_state, 该点以前的权值作为 old_state, 判断 old_state 是否完全包含 new_state,即判断是否有从新的源点出发的路径来访问该节点,如果是,则更新该节点的状态。

    • 如果该节点的状态被更新, 将该节点所有的出边的权值都设为该节点的状态,并且将该边所指向的节点加入下一次迭代的队列。

  • 入边权值与出边权值共用带来的问题
      通过上述方式实现后,发现求出的图的直径与实际值差距较大,通过分析源代码之后,发现: 对于同一条边对应的入边和出边, 它们所对应的权值指向通一块存储地址,也就是说:入边和出边的权值始终都是一样的,这在异步执行的情况下就引入了一个问题:在同一次迭代中, 对于同一条边,如果出现某个节点把出边的权值修改, 而有节点需要使用入边的权值, 此时使用的权值不是上一次迭代传来的权值,而是新的权值。

      为了解决这个问题, 对于边的权值, 引入了两个权值的概念: “当前权值” 和“下一轮权值”, 在一次迭代中, 对入边的访问,使用“当前权值”,而对于出边的修改, 使用“下一轮权值”。

版权声明:本文为博主原创文章,未经博主允许不得转载。

近似直径算法的 GraphChi 实现

标签:graphchi   图计算   

原文地址:http://blog.csdn.net/sunliymonkey/article/details/47983349

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!