首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在两次调用Vertex.getEdgeValue()之后,Vertex.getEdgeValue不一样

在两次调用Vertex.getEdgeValue()之后,Vertex.getEdgeValue不一样
EN

Stack Overflow用户
提问于 2015-05-21 21:47:47
回答 1查看 59关注 0票数 1

我试图在gi相图中实现旋转图划分算法。在第一步中,我的程序将边添加到给定的输入图中,这样它就变成了一个无向图,每个顶点都选择了一个随机分区。(这个分区-整数存储在VertexValue中)在这个初始化步骤的末尾,每个顶点发送一条消息给所有带有顶点ID ( LongWritable)和顶点选择的分区的输出边。

一切都很好。现在,在我遇到麻烦的步骤中,每个顶点迭代接收到的消息,并将接收到的分区保存在相应边缘的EdgeValue中。(VertexValueV in Vertex<I,V,E>EdgeValueE in Edge<I,E>)

下面是我代码的重要部分:

包装类:

代码语言:javascript
复制
public class EdgeValue implements Writable {
private int weight;
private int partition;
// Getters and setters for weight and partition
    public EdgeValue() {
    this.weight = -2;
    this.partition = -1;
}
// Constructors taking 1 and 2 ints and setting weight/partition to the given value

@Override
public void readFields(DataInput in) throws IOException {
    this.weight = in.readInt();
    this.partition = in.readInt();
}

@Override
public void write(DataOutput out) throws IOException {
    out.writeInt(this.weight);
    out.writeInt(this.partition);
}
}

public class SpinnerMessage implements Writable, Configurable {
private long senderId;
private int updatePartition;
public SpinnerMessage() {
    this.senderId = -1;
    this.updatePartition = -1;
}
// Constructors taking int and/or LongWritable and setting the fields
// Getters and setters for senderId and updatePartition

@Override
public void readFields(DataInput in) throws IOException {
    this.senderId = in.readLong();
    this.updatePartition = in.readInt();
}

@Override
public void write(DataOutput out) throws IOException {
    out.writeLong(this.senderId);
    out.writeInt(this.updatePartition);
}
}

前面步骤中的compute方法(ran是一个Random对象):

代码语言:javascript
复制
public void compute(Vertex<LongWritable, VertexValue, EdgeValue> vertex, Iterable<LongWritable> messages) {
    int initialPartition = this.ran.nextInt(GlobalInformation.numberOfPartitions);
    vertex.getValue().setPartition(initialPartition);
    sendMessageToAllEdges(vertex, new SpinnerMessage(vertex.getId(),initialPartition));
}

bug发生的步骤中的compute方法:

代码语言:javascript
复制
public void compute(Vertex<LongWritable, VertexValue, EdgeValue> vertex,Iterable<SpinnerMessage> messages) throws IOException {
for (SpinnerMessage m : messages) {
    vertex.getEdgeValue(new LongWritable(m.getSenderWritable().get())).setPartition(m.getUpdatePartition());
}
// ... some other code, e.g. initializing the amountOfNeighbors array.
// Here I get an ArrayIndexOutOfBoundsException since the partition is -1:
for (Edge<LongWritable, EdgeValue> edge : vertex.getEdges()) {
    EdgeValue curValue = edge.getValue();
    amountOfNeighbors[curValue.getPartition()] += curValue.getWeight();
}

但是,当我在边上迭代的时候。

代码语言:javascript
复制
for(Edge<LongWritable, EdgeValue> e : vertex.getEdges())

或通过

代码语言:javascript
复制
vertex.getEdgeValue(someVertex)

然后返回的EdgeValue具有权重-2和分区-1 (来自标准构造函数的默认值)。

我的想法是什么会导致这个错误:

  1. getEdgeValue(new LongWritable(someLong))可能无法工作,因为它将是与具有相同值的另一个new LongWritable(someLong)不同的对象。但是,我已经在gi相图代码中看到了这一点,所以这似乎是没有问题的,只有保存在LongWritable中的长时间似乎很重要。
  2. (最有可能导致) Hadoop序列化和反序列化正在以某种方式改变我的EdgeValue对象。由于Hadoop用于非常大的图形,它们可能不适合RAM。为此,VertexValueEdgeValue必须实现Writable。但是,在在线检查了一些gi相图代码之后,我以一种对我来说似乎正确的方式实现了read()write() (按相同的顺序编写和读取重要字段)。(我认为这在某种程度上与问题有关,因为在第二个调用中返回的EdgeValue具有标准构造函数的字段值)

我还在文档中读到了一点:

E getEdgeValue(I targetVertexId)返回具有给定目标顶点id的第一条边的值,如果没有这样的边,则返回null。注意:此方法返回的边缘值对象可能在下一次调用中失效。因此,保持对边缘值的引用几乎总是导致不想要的行为。

但是,这并不适用于我,因为我只有一个EdgeValue变量,对吗?

提前感谢大家花时间来帮助我。(我使用Hadoop1.2.1和gi饼1.2.0)

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-05-25 23:35:17

在查看了一些更多的gi相图代码示例之后,我找到了解决方案:Vertex.getEdgeValue()方法基本上创建了顶点的EdgeValue副本。如果您更改它返回的对象,它将不会将这些更改写回磁盘。要在EdgeValueVertexValue中保存信息,必须使用setVertexValue()setEdgeValue()

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30384947

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档