El algoritmo pregel en Spark GraphX

Introducción al código fuente de la función pregel y cada parámetro:

  def pregel[A: ClassTag](
      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] = {
    
    
    Pregel(graph, initialMsg, maxIterations, activeDirection)(vprog, sendMsg, mergeMsg)
  }
parámetro Descripción
initialMsg Cuando se inicializa el gráfico, cuando comienza el cálculo del modelo, todos los nodos recibirán un mensaje primero
maxIteraciones El número máximo de iteraciones
activeDirection Especifica la dirección para enviar el mensaje.
vprog El nodo llama al mensaje para fusionar los datos agregados con los atributos del nodo.
sendMsg Los nodos activos llaman a este método para enviar mensajes
mergeMsg Si un nodo recibe varios mensajes, mergeMsg se usa para agregar los mensajes múltiples en un solo mensaje. Si el nodo recibe solo un mensaje, esta función no se llama

Ejemplo: encuentra la distancia más corta desde el vértice 5 a otros vértices


Antes de entender el caso, primero debemos aclarar dos puntos de conocimiento sobre el vértice:

  1. Hay dos estados de vértices:
    (1), estado de pasivación [similar a inactividad, no hacer nada]
    (2), estado activo [trabajo]
  2. El vértice puede estar en estado activo, existen condiciones:
    (1), el mensaje se recibió con éxito o
    (2), cualquier mensaje se envió con éxito
	//1、创建SparkContext
    val spark: SparkConf = new SparkConf().setAppName("PregelDemo")
      .setMaster("local[*]")
    val sc = new SparkContext(spark)
    //2、创建顶点
    val vertexArray = Array(
      (1L, ("Alice", 28)),
      (2L, ("Bob", 27)),
      (3L, ("Charlie", 65)),
      (4L, ("David", 42)),
      (5L, ("Ed", 55)),
      (6L, ("Fran", 50))
    )
    val vertexRDD: RDD[(VertexId, (String,Int))] = sc.makeRDD(vertexArray)
    //3、创建边,边的属性代表 相邻两个顶点之间的距离
    val edgeArray = Array(
      Edge(2L, 1L, 7),
      Edge(2L, 4L, 2),
      Edge(3L, 2L, 4),
      Edge(3L, 6L, 3),
      Edge(4L, 1L, 1),
      Edge(2L, 5L, 2),
      Edge(5L, 3L, 8),
      Edge(5L, 6L, 3)
    )
    val edgeRDD: RDD[Edge[Int]] = sc.makeRDD(edgeArray)
    //4、创建图(使用aply方式创建)
    val graph1 = Graph(vertexRDD, edgeRDD)

    /* ************************** 使用pregle算法计算,顶点5 到 各个顶点的最短距离 ************************** */

    //被计算的图中 起始顶点id
    val srcVertexId = 5L
    val initialGraph: Graph[Double, PartitionID] = graph1.mapVertices{
    
    case (vid,(name,age)) => if(vid==srcVertexId) 0.0 else Double.PositiveInfinity}
//    initialGraph.vertices.collect().foreach(println)

    //5、调用pregel
    val pregelGraph: Graph[Double, PartitionID] = initialGraph.pregel(
      Double.PositiveInfinity,
      Int.MaxValue,
      EdgeDirection.Out
    )(
      (vid: VertexId, vd: Double, distMsg: Double) => {
    
    
        val minDist: Double = math.min(vd, distMsg)
        println("vprog: " + vid + " " + vd + " " + distMsg + " " + minDist)
        minDist
      },
      (edgeTriplet: EdgeTriplet[Double,PartitionID]) => {
    
    
        if (edgeTriplet.srcAttr + edgeTriplet.attr < edgeTriplet.dstAttr) {
    
    
          println("sendMsg " + edgeTriplet.srcId + " " + edgeTriplet.srcAttr+" "+
            edgeTriplet.dstId + " " + edgeTriplet.dstAttr+" "+edgeTriplet.attr)
          Iterator[(VertexId,Double)]((edgeTriplet.dstId,edgeTriplet.srcAttr+edgeTriplet.attr))
        } else {
    
    
          Iterator.empty
        }
      },
      (msg1: Double, msg2: Double) => {
    
    
        println("msg1: "+msg1+"msg2: "+msg2)
        math.min(msg1, msg2)
      }
    )
    println("输出结果:")
    pregelGraph.triplets.collect().foreach(println)
    println()
    pregelGraph.vertices.collect().foreach(println)

El resultado es el siguiente (omita la impresión de otros procesos intermedios):

(1,15.0)
(2,12.0)
(3,8.0)
(4,14.0)
(5,0.0)
(6,3.0)

pregel 原理分析


Antes de llamar al método pregel, inicialice las propiedades de cada vértice del gráfico como se muestra en la siguiente figura: la distancia desde el vértice 5 a sí mismo es 0, así que configúrelo en 0, y todos los demás vértices se establecen en infinito positivo Doble.

Cuando se llama al método pregel:

Primero, todos los vértices recibirán un mensaje inicial initialMsg , de modo que todos los vértices estén en estado activo (nodos marcados en rojo).

Inserte la descripción de la imagen aquí

Comienza la primera iteración:

Todos los vértices usan la dirección del borde de EdgeDirection.Out para llamar al método sendMsg para enviar un mensaje al vértice de destino. Si el atributo del vértice de origen + el atributo del borde <el atributo del vértice de destino, el mensaje se envía. De lo contrario, no se enviará.
Solo se envían dos lados con éxito:
5—> 3 (0 + 8 <Doble.Infinito, éxito),
5—> 6 (0 + 3 <Doble.Infinito, éxito)
3—> 2 (Doble.Infinito + 4> Doble .Infinito, falla)
3—> 6 (Doble.Infinito + 3> Doble.Infinito, falla)
2—> 1 (Doble.Infinito + 7> Doble.Infinito, falla)
2—> 4 (Doble.Infinito + 2> Doble.Infinito, falla)
2—> 5 (Doble.Infinito + 2> Doble.Infinito, falla)
4—> 1 (Doble.Infinito + 1> Doble.Infinito, falla)


Una vez completada la ejecución del método sendMsg , de acuerdo con la condición de que el vértice esté en estado activo, el vértice 5 envió mensajes con éxito al vértice 3 y al vértice 6 respectivamente, y el vértice 3 y el vértice 6 también recibieron correctamente el mensaje. Entonces, solo tres vértices 5, 3 y 6 están activos en este momento, y todos los demás vértices están pasivados. Luego, tanto el vértice 3 como el vértice 6 que recibieron el mensaje llaman al método vprog para fusionar el mensaje recibido con sus propios atributos. Como se muestra en la Figura 2 a continuación. El final de la primera iteración.
Inserte la descripción de la imagen aquí

Comienza la segunda iteración:

El vértice 3 no pudo enviar un mensaje al vértice 6 y el vértice 3 envió un mensaje al vértice 2 con éxito. En este momento, el vértice 3 envió correctamente el mensaje y el vértice 2 recibió correctamente el mensaje, por lo que el vértice 2 y el vértice 3 se activaron. y otros vértices se pasivaron. Luego, el vértice 2 llama al método vprog para fusionar el mensaje recibido con sus propios atributos. Consulte la Figura 3. Hasta ahora, la segunda iteración ha terminado.
Inserte la descripción de la imagen aquí

Comienza la tercera iteración:

El vértice 3 envía mensajes al vértice 2 falla y al vértice 6 falla, el vértice 2 envía mensajes al vértice 1 éxito, al vértice 4 éxito y al vértice 5 falla, por lo que el vértice 2, el vértice 1 y el vértice 4 se activan y otros vértices tienen un estado aburrido . El vértice 1 y el vértice 4 llaman respectivamente al método vprog para fusionar el mensaje recibido con sus propios atributos. Ver figura 4. Hasta ahora, la tercera iteración ha terminado.
Inserte la descripción de la imagen aquí

Comienza la cuarta iteración:

El vértice 2 no pudo enviar mensajes al vértice 1 y el vértice 4 falló. El vértice 4 envía un mensaje al vértice 1 con éxito, el vértice 1 y el vértice 4 entran en estado activo y otros vértices entran en estado pasivado. Vertex 1 llama al método vprog para fusionar el mensaje recibido con sus propios atributos
Inserte la descripción de la imagen aquí

Comienza la quinta iteración:

El vértice 4 no envía un mensaje al vértice 1 nuevamente, el vértice 4 y el vértice 1 entran en el estado de pasivación, en este momento todo el gráfico entra en el estado de pasivación. Terminar aqui
Inserte la descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/qq_42578036/article/details/110194141
Recomendado
Clasificación