[论文笔记]流式图分区方法的实验研究

Streaming Graph Partitioning: An Experimental Study

本文介绍了主流的几种流式图分区方法,并设置实验比较了它们的性能。

研究背景

在分布式计算流行的当下,图分区是一项非常基础且重要的技术。对大多数图算法而言,如果想要将之置于分布式环境下并行执行,必须对输入的图结构进行分区处理。典型的图算法有SSSF,PageRank,Connected Component,Label Propagation等。
图分区不是一项简单的工作,一个理想的图分区方式应该达到两个目标:

  1. 各分区负载均衡;
  2. 分区之间的通信最小。

目标1可以让各结点的计算时间接近,减少等待时间。目标2可以减轻网络负载,加快整体执行效率。事实上,实现这两个目标是个NP问题,人们只能采用启发式的算法进行图分区,以求尽可能地接近这两个目标。
另一方面,现在的图数据规模越来越大,一台机器的内存很难装下整张图。为了对大图进行分区,人们提出了流式图分区算法,将图元素以流的形式读入内存,根据全局信息和分区算法为其计算所属分区,这样只需将整张图以流的形式过一遍,即可完成整个图分区。

图分区方式主要分为点分区和边分区两类。

  1. 点分区把顶点集切分成几块,装入不同的分区。若一条边的首尾顶点被分到了不同的区域,那么这条边就是跨分区的边。显然,顶点通过这条边进行通信时会带来分区间的网络开销,所以跨分区的边越少越好。
  2. 边分区把边集切分成若干部分,分配到不同的区域。这样会出现的情况是一个顶点的边同时属于不同的分区,这时该顶点同时在这些分区中存在并互为镜像顶点。执行图算法时它们之间需要进行通信,带来网络开销。因此,这类顶点的数量越少越好。

图分区方法

本文主要介绍了8种图分区算法:Hash,LDG,Fennel,Greedy,HDRF,DBH,Grid,PDS。下图为各算法的比较。
在这里插入图片描述
Hash
哈希分区的思路很简单,将图元素的ID作为hash key,映射到分区ID。哈希分区分为点哈希(V->N)和边哈希(E->N)两种方式。由于哈希分区不需要任何先验数据,因此它可以处理无边界流,即理论上可以处理无限大的图。

Linear Deterministic Greedy(LDG)
LDG是一种贪心算法,它以顶点作为输入流,是一种点分区算法。它希望能把顶点分配到邻居最多的分区,以减小跨分区边的数量。LDG需要保存之前的顶点信息,因此不适用于无边界流。其伪代码如图所示。

在这里插入图片描述
Fennel
Fennel与LDG相似,也希望将顶点放入邻居最多的分区,同样不适合无边界流。其伪代码如下所示。
在这里插入图片描述

Greedy
Greedy是以边作为输入流的贪心算法,是一种边分区算法。算法希望最小化镜像顶点数,同时保持各分区负载均衡。设边的首尾顶点为v1和v2,设S(v)为拥有顶点v的分区集。每条边的分区规则如下图伪代码所示。

在这里插入图片描述
Greedy算法只需要维护少量全局数据,因此理论上可以处理无边界流。

HDRF
HDRF是以边作为输入流的边分区算法,是为幂律分布图设计的图分区方法。其基本思路是优先对度数高的顶点进行切分,这样可以最小化镜像顶点的数量。其伪代码如下。

在这里插入图片描述
其中部分参数定义如下:
在这里插入图片描述
可以看到,对于一条输入边(v1,v2),优先选择拥有v1或v2并且负载较小的分区,同时比较v1和v2的度,优先选择度较小者所在的分区。与Greedy相似,HDRF算法只需要维护少量全局数据,因此可以处理无边界流。

Degree Based Hashing(DBH)
DBH算法与HDRF算法相似,也是以边为输入流的边分区算法,优先切分度数高的顶点。与HDRF不同的是,DBH采用哈希分区策略,因此形式上较为简单。DBH同样适用于无边界流,其伪代码如下。

在这里插入图片描述

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MyBatis并没有提供专门的流式查询接口方法,但是可以通过设置`fetchSize`参数来实现类似的效果。下面是一个示例代码,演示了如何使用MyBatis进行流式查询: ```java public List<User> selectUsersWithStream() { SqlSession sqlSession = sqlSessionFactory.openSession(); List<User> userList = new ArrayList<>(); try { // 设置 fetchSize 参数 sqlSession.setDefaultFetchSize(100); // 获取 Mapper 接口实例 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); // 调用查询方法,返回结果集 ResultSet ResultSet rs = userMapper.selectUsersResultSet(); // 遍历结果集,将每一行记录转换为 User 对象,并添加到结果列表中 while (rs.next()) { User user = new User(); user.setId(rs.getInt("id")); user.setName(rs.getString("name")); user.setAge(rs.getInt("age")); userList.add(user); } } catch (SQLException e) { e.printStackTrace(); } finally { sqlSession.close(); } return userList; } ``` 上述代码中,我们首先通过`SqlSessionFactory`获取一个`SqlSession`实例,然后设置`fetchSize`参数为100,接着获取`UserMapper`接口实例,调用`selectUsersResultSet()`方法,返回结果集`ResultSet`。通过遍历结果集,将每一行记录转换为`User`对象,并添加到结果列表中,最终返回结果列表。 需要注意的是,在使用`ResultSet`进行查询时,需要手动关闭`SqlSession`,以释放占用的资源。同时,也需要确保数据库驱动支持`fetchSize`参数,否则可能会出现异常。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值