Giraph调试奇怪问题记录

本文介绍了一种基于Giraph实现的高效连通组件(HCC)算法,该算法通过传播最小顶点ID来标识图中的连通组件。文章详细阐述了算法的工作原理及其实现过程,包括不同超步阶段的具体操作。

/*
 * 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.giraph.examples;

import org.apache.giraph.graph.BasicComputation;
import org.apache.giraph.graph.DefaultVertex;
import org.apache.giraph.graph.GraphTaskManager;
import org.apache.giraph.edge.ArrayListEdges;
import org.apache.giraph.edge.Edge;
import org.apache.giraph.edge.EdgeFactory;
import org.apache.giraph.edge.EdgeNoValue;
import org.apache.giraph.graph.Vertex;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.NullWritable;

import java.io.IOException;
import java.util.ArrayList;

/**
 * Implementation of the HCC algorithm that identifies connected components and
 * assigns each vertex its "component identifier" (the smallest vertex id
 * in the component)
 *
 * The idea behind the algorithm is very simple: propagate the smallest
 * vertex id along the edges to all vertices of a connected component. The
 * number of supersteps necessary is equal to the length of the maximum
 * diameter of all components + 1
 *
 * The original Hadoop-based variant of this algorithm was proposed by Kang,
 * Charalampos, Tsourakakis and Faloutsos in
 * "PEGASUS: Mining Peta-Scale Graphs", 2010
 *
 * http://www.cs.cmu.edu/~ukang/papers/PegasusKAIS.pdf
 */
@Algorithm(
    name = "Connected components",
    description = "Finds connected components of the graph"
)
public class RecodeComputation extends
    BasicComputation<IntWritable, IntWritable, NullWritable, IntWritable> {
  /**
   * 1.0号超步写入zk各自分区的顶点数量。
   * 2.1号超步所有分区根据zk各自更新ID, 并发送更新后的顶点消息.
   * 3.更新接收的顶点ID。
   */
  @Override
  public void compute(
      Vertex<IntWritable, IntWritable, NullWritable> vertex,
      Iterable<IntWritable> messages) throws IOException {
    if (getSuperstep() == 0) {  
      GraphTaskManager.LOG.info("Vertex " + vertex.toString()) ;
    	sendMessageToAllEdges(vertex, vertex.getId()) ; //向目标顶点发送源顶点ID
      return;
    }
    
    if (getSuperstep() == 1) {   //1.每个目标顶点将收到的消息保存,并汇总为入度顶点集合,清空出度边集合,并将出度边集合复用。
    	ArrayListEdges edges = (ArrayListEdges) vertex.getEdges() ;
    	edges.clear() ;
    	
	   for (IntWritable srcId : messages) {
		   GraphTaskManager.LOG.info("Received Messags : " + srcId.toString() ) ;
		   Integer src = srcId.get() ;
		   ((DefaultVertex)vertex).inEdges.add(new IntWritable(src)) ;
	   }
	   
	   StringBuffer sb = new StringBuffer() ;
	   ArrayList<IntWritable> inEdges = ((DefaultVertex)vertex).inEdges ;
	  for(IntWritable inEdge : inEdges) {
		  GraphTaskManager.LOG.info("inEdge " + inEdge.toString() ) ;
		  sb.append(inEdge.toString()) ;		  
	  }
	   
	   GraphTaskManager.LOG.info("New Edges " + vertex.toString() + sb.toString() + " at step " + getSuperstep()) ;
      return;
    }
    
    if(getSuperstep() == 2) {   //2.每个分区根据顶点数量确定各自分区顶点的起始编码,并按照递增的顺序对本分区内部所有顶点ID进行更新,各顶点更新自己的ID后,将更新后的新ID作为消息。按照超步1中获取的入度顶点集合进行发送。 
    	ArrayList<IntWritable> inEdges = ((DefaultVertex)vertex).inEdges ;
    	for (IntWritable srcId : inEdges) {
	           GraphTaskManager.LOG.info("Send New id : " + vertex.toString()  + " to " + srcId + " at step " + getSuperstep()) ;
	           sendMessage(srcId, vertex.getId()) ; //向原来的入度边发送自己的新ID
    	}
    }
    
    if(getSuperstep() == 3) {   //3.每个顶点收到的消息作为新的出度边。 
    	ArrayListEdges edges = (ArrayListEdges) vertex.getEdges() ;
 	   edges.clear(); //当前edges实为入度边集合
    	for (IntWritable srcId : messages) {
    		 Integer src = srcId.get() ;
 		   ((ArrayListEdges)vertex.getEdges()).add(EdgeFactory.createReusable(new IntWritable(src))) ;
 	   }
 	   GraphTaskManager.LOG.info("new Edges " + vertex.toString() +  edges.printEdges() + " at step " + getSuperstep()) ;
 	   vertex.voteToHalt() ;
    }
  }
}


自定义Giraph1.1.0的重编码计算类,其中超步3中如果这样写:

for (IntWritable srcId : messages) {
 		   ((ArrayListEdges)vertex.getEdges()).add(EdgeFactory.createReusable(srcId)) ;

在以上写法中,会造成迭代中值重复,原因还没想明白。



修改后的重编码类:

public class RecodeComputation extends
    BasicComputation<IntWritable, IntWritable, NullWritable, IntWritable> {
  /**
   * 1.0号超步写入zk各自分区的顶点数量。
   * 2.1号超步所有分区根据zk各自更新ID, 并发送更新后的顶点消息.
   * 3.更新接收的顶点ID。
   */
  @Override
  public void compute(
      Vertex<IntWritable, IntWritable, NullWritable> vertex,
      Iterable<IntWritable> messages) throws IOException {
    if (getSuperstep() == 0) {  
    	sendMessageToAllEdges(vertex, vertex.getId()) ; //向目标顶点发送源顶点ID
      return;
    }
    
    if (getSuperstep() == 1) {   //1.每个目标顶点将收到的消息保存,并汇总为入度顶点集合,清空出度边集合,并将出度边集合复用。
	   for (IntWritable srcId : messages) {
		   Integer src = srcId.get() ;
		   ((DefaultVertex)vertex).inEdges.add(new IntWritable(src)) ;
	   }
      return;
    }
    
    if(getSuperstep() == 2) {   //2.每个分区根据顶点数量确定各自分区顶点的起始编码,并按照递增的顺序对本分区内部所有顶点ID进行更新,各顶点更新自己的ID后,将更新后的新ID作为消息。按照超步1中获取的入度顶点集合进行发送。 
    	ArrayList<IntWritable> inEdges = ((DefaultVertex)vertex).inEdges ;
    	for (IntWritable srcId : inEdges) {
	           sendMessage(srcId, vertex.getId()) ; //向原来的入度边发送自己的新ID
    	}
    }
    
    if(getSuperstep() == 3) {   //3.每个顶点收到的消息作为新的出度边。 
    	ArrayListEdges edges = (ArrayListEdges) vertex.getEdges() ;
 	   edges.clear(); //当前edges实为入度边集合
    	for (IntWritable srcId : messages) {
    		 Integer src = srcId.get() ;
 		   ((ArrayListEdges)vertex.getEdges()).add(EdgeFactory.createReusable(new IntWritable(src))) ;
 	   }
 	   vertex.voteToHalt() ;
    }
  }
}



先看效果: https://renmaiwang.cn/s/jkhfz Hue系列产品将具备高度的个性化定制能力,并且借助内置红、蓝、绿三原色LED的灯泡,能够混合生成1600万种不同色彩的灯光。 整个操作流程完全由安装于iPhone上的应用程序进行管理。 这一创新举措为智能照明控制领域带来了新的启示,国内相关领域的从业者也积极投身于相关研究。 鉴于Hue产品采用WiFi无线连接方式,而国内WiFi网络尚未全面覆盖,本研究选择应用更为普及的蓝牙技术,通过手机蓝牙与单片机进行数据交互,进而产生可调节占空比的PWM信号,以此来控制LED驱动电路,实现LED的调光功能以及DIY调色方案。 本文重点阐述了一种基于手机蓝牙通信的LED灯设计方案,该方案受到飞利浦Hue智能灯泡的启发,但考虑到国内WiFi网络的覆盖限制,故而选用更为通用的蓝牙技术。 以下为相关技术细节的详尽介绍:1. **智能照明控制系统**:智能照明控制系统允许用户借助手机应用程序实现远程控制照明设备,提供个性化的调光及色彩调整功能。 飞利浦Hue作为行业领先者,通过红、蓝、绿三原色LED的混合,能够呈现1600万种颜色,实现了全面的定制化体验。 2. **蓝牙通信技术**:蓝牙技术是一种低成本、短距离的无线传输方案,工作于2.4GHz ISM频段,具备即插即用和强抗干扰能力。 蓝牙协议栈由硬件层和软件层构成,提供通用访问Profile、服务发现应用Profile以及串口Profiles等丰富功能,确保不同设备间的良好互操作性。 3. **脉冲宽度调制调光**:脉冲宽度调制(PWM)是一种高效能的调光方式,通过调节脉冲宽度来控制LED的亮度。 当PWM频率超过200Hz时,人眼无法察觉明显的闪烁现象。 占空比指的...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值