/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ package org.apache.spark.graphx import scala.reflect.ClassTag
import org.apache.spark.Logging /**
* Implements a Pregel-like bulk-synchronous message-passing API.
*
* Unlike the original Pregel API, the GraphX Pregel API factors the sendMessage computation over
* edges, enables the message sending computation to read both vertex attributes, and constrains
* messages to the graph structure. These changes allow for substantially more efficient
* distributed execution while also exposing greater flexibility for graph-based computation.
*
* @example We can use the Pregel abstraction to implement PageRank:
* {{{
* val pagerankGraph: Graph[Double, Double] = graph
* // Associate the degree with each vertex
* .outerJoinVertices(graph.outDegrees) {
* (vid, vdata, deg) => deg.getOrElse(0)
* }
* // Set the weight on the edges based on the degree
* .mapTriplets(e => 1.0 / e.srcAttr)
* // Set the vertex attributes to the initial pagerank values
* .mapVertices((id, attr) => 1.0)
*
* def vertexProgram(id: VertexId, attr: Double, msgSum: Double): Double =
* resetProb + (1.0 - resetProb) * msgSum
* def sendMessage(id: VertexId, edge: EdgeTriplet[Double, Double]): Iterator[(VertexId, Double)] =
* Iterator((edge.dstId, edge.srcAttr * edge.attr))
* def messageCombiner(a: Double, b: Double): Double = a + b
* val initialMessage = 0.0
* // Execute Pregel for a fixed number of iterations.
* Pregel(pagerankGraph, initialMessage, numIter)(
* vertexProgram, sendMessage, messageCombiner)
* }}}
*
*/
object Pregel extends Logging { /**
* Execute a Pregel-like iterative vertex-parallel abstraction. The
* user-defined vertex-program `vprog` is executed in parallel on
* each vertex receiving any inbound messages and computing a new
* value for the vertex. The `sendMsg` function is then invoked on
* all out-edges and is used to compute an optional message to the
* destination vertex. The `mergeMsg` function is a commutative
* associative function used to combine messages destined to the
* same vertex.
*
* On the first iteration all vertices receive the `initialMsg` and
* on subsequent iterations if a vertex does not receive a message
* then the vertex-program is not invoked.
*
* This function iterates until there are no remaining messages, or
* for `maxIterations` iterations.
*
* @tparam VD the vertex data type
* @tparam ED the edge data type
* @tparam A the Pregel message type
*
* @param graph the input graph.
*
* @param initialMsg the message each vertex will receive at the on
* the first iteration
*
* @param maxIterations the maximum number of iterations to run for
*
* @param activeDirection the direction of edges incident to a vertex that received a message in
* the previous round on which to run `sendMsg`. For example, if this is `EdgeDirection.Out`, only
* out-edges of vertices that received a message in the previous round will run. The default is
* `EdgeDirection.Either`, which will run `sendMsg` on edges where either side received a message
* in the previous round. If this is `EdgeDirection.Both`, `sendMsg` will only run on edges where
* *both* vertices received a message.
*
* @param vprog the user-defined vertex program which runs on each
* vertex and receives the inbound message and computes a new vertex
* value. On the first iteration the vertex program is invoked on
* all vertices and is passed the default message. On subsequent
* iterations the vertex program is only invoked on those vertices
* that receive messages.
*
* @param sendMsg a user supplied function that is applied to out
* edges of vertices that received messages in the current
* iteration
*
* @param mergeMsg a user supplied function that takes two incoming
* messages of type A and merges them into a single message of type
* A. ''This function must be commutative and associative and
* ideally the size of A should not increase.''
*
* @return the resulting graph at the end of the computation
*
*/
def apply[VD: ClassTag, ED: ClassTag, A: ClassTag]
(graph: Graph[VD, ED],
initialMsg: A,
maxIterations: Int = Int.MaxValue,
activeDirection: EdgeDirection = EdgeDirection.Either)
(vprog: (VertexId, VD, A) => VD,
sendMsg: EdgeTriplet[VD, ED] => Iterator[(VertexId, A)],
mergeMsg: (A, A) => A)
: Graph[VD, ED] =
{
var g = graph.mapVertices((vid, vdata) => vprog(vid, vdata, initialMsg)).cache()
// compute the messages
var messages = g.mapReduceTriplets(sendMsg, mergeMsg)
var activeMessages = messages.count()
// Loop
var prevG: Graph[VD, ED] = null
var i = 0
while (activeMessages > 0 && i < maxIterations) {
// Receive the messages. Vertices that didn't get any messages do not appear in newVerts.
val newVerts = g.vertices.innerJoin(messages)(vprog).cache()
// Update the graph with the new vertices.
prevG = g
g = g.outerJoinVertices(newVerts) { (vid, old, newOpt) => newOpt.getOrElse(old) }
g.cache() val oldMessages = messages
// Send new messages. Vertices that didn't get any messages don't appear in newVerts, so don't
// get to send messages. We must cache messages so it can be materialized on the next line,
// allowing us to uncache the previous iteration.
messages = g.mapReduceTriplets(sendMsg, mergeMsg, Some((newVerts, activeDirection))).cache()
// The call to count() materializes `messages`, `newVerts`, and the vertices of `g`. This
// hides oldMessages (depended on by newVerts), newVerts (depended on by messages), and the
// vertices of prevG (depended on by newVerts, oldMessages, and the vertices of g).
activeMessages = messages.count() logInfo("Pregel finished iteration " + i) // Unpersist the RDDs hidden by newly-materialized RDDs
oldMessages.unpersist(blocking=false)
newVerts.unpersist(blocking=false)
prevG.unpersistVertices(blocking=false)
prevG.edges.unpersist(blocking=false)
// count the iteration
i += 1
} g
} // end of apply } // end of class Pregel

GraphX之Pregel(BSP模型-消息传递机制)学习的更多相关文章

  1. Android学习笔记-事件处理之Handler消息传递机制

    内容摘要:Android Handler消息传递机制的学习总结.问题记录 Handler消息传递机制的目的: 1.实现线程间通信(如:Android平台只允许主线程(UI线程)修改Activity里的 ...

  2. Android学习之Handler消息传递机制

    Android只允许UI线程修改Activity里的UI组件.当Android程序第一次启动时,Android会同时启动一条主线程(Main Thread),主线程主要负责处理与UI相关的事件,如用户 ...

  3. 从BSP模型到Apache Hama

    一.什么是BSP模型 概述 BSP(Bulk Synchronous Parallel,整体同步并行计算模型)是一种并行计算模型,由英国计算机科学家Viliant在上世纪80年代提出.Google发布 ...

  4. BSP模型

    http://www.uml.org.cn/yunjisuan/201212191.asp Hama中最关键的就是BSP(Bulk Synchronous Parallel-"大型" ...

  5. 我理解的Hanlder--android消息传递机制

    每一个学习Android的同学都会觉得Handler是一个神奇的东西,我也一样,开始我以为我懂了Handler的机制,后来发现自己是一知半解,昨天想想,我能否自己实现一个Handler,让子线程与Ac ...

  6. Chrome 消息传递机制

    Chrome插件开发入门(二)——消息传递机制 Blog | Qiushi Chen 2014-03-31 9538 阅读 Chrome 插件 由于插件的js运行环境有区别,所以消息传递机制是一个重要 ...

  7. Chrome插件开发入门(二)——消息传递机制

    Chrome插件开发入门(二)——消息传递机制   由于插件的js运行环境有区别,所以消息传递机制是一个重要内容.阅读了很多博文,大家已经说得很清楚了,直接转一篇@姬小光 的博文,总结的挺好.后面附一 ...

  8. iOS开发——OC篇&消息传递机制(KVO/NOtification/Block/代理/Target-Action)

     iOS开发中消息传递机制(KVO/NOtification/Block/代理/Target-Action)   今晚看到了一篇好的文章,所以就搬过来了,方便自己以后学习 虽然这一期的主题是关于Fou ...

  9. (Android数据传递)Intent消息传递机制 “Intent”“数据传递”

    Intent类的继承关系:   需要注意的是,该类实现了Parcelable(用于数据传递)和Cloneable接口. Intent是一种(系统级别的)消息传递机制,可以在应用程序内使用,也可以在应用 ...

随机推荐

  1. Springboot学习05-自定义错误页面完整分析

    Springboot学习06-自定义错误页面完整分析 前言 接着上一篇博客,继续分析Springboot错误页面问题 正文 1-自定义浏览器错误页面(只要将自己的错误页面放在指定的路径下即可) 1-1 ...

  2. ES6的let和const的不同点

    详细的异同点请点击:https://blog.csdn.net/zhouziyu2011/article/details/71366078

  3. Maven Nexus3 安装,私服搭建

    为啥搭建Maven私服? 如果没有私服,我们所需的所有构件都需要通过maven的中央仓库和第三方的Maven仓库下载到本地,而一个团队中的所有人都重复的从maven仓库下载构件无疑加大了仓库的负载和浪 ...

  4. golang环境 centos 7

    https://blog.csdn.net/ggq89/article/details/82682171  Linux下Go的安装.配置 .升级和卸载 https://blog.csdn.net/we ...

  5. 【轻松前端之旅】CSS入门

    编写css,很自然的思路: 1.给哪些元素添加样式呢?选择器技术就解决这个问题. 2.添加哪些样式?这就要了解css样式属性及它的值对应的显示规则了. 因此,学习css首先要学的就是选择器,至于样式属 ...

  6. 卓豪ManageEngine参加2018企业数字化转型与CIO职业发展高峰论坛

    卓豪ManageEngine参加2018企业数字化转型与CIO职业发展高峰论坛 2018年10月20日,78CIO APP在北京龙城温德姆酒店主办了主题为“新模式.新动能.新发展”的<2018企 ...

  7. 微信浏览器Ajax请求返回值走error

    微信浏览器Ajax post请求是返回值走的error $.ajax({ type: "POST", url: "https://XXXX", cache: f ...

  8. 2019.03.02 bzoj2565: 最长双回文串(pam)

    传送门 题意简述:问最长的由两个回文串连接而成最长字串长度. 思路: 正反串各建一个pampampam然后就完了. 代码: #include<bits/stdc++.h> #define ...

  9. List 接口中ArrayList Vector LinkedList 比较

    访问权限Arryist最快 其次Vector  最慢LinkedList

  10. windows server防火墙添加例外的步骤

      Windows Server 2012 防火墙如何添加端口例外的方法 在Windows Server 2012系统中,如果用户想在防火墙中开通一个端口,您可以按以下步骤执行: 1. 首先点击桌面左 ...