调用 Vertex.getEdgeValue() 两次后 EdgeValue 不一样
EdgeValue isnt the same after calling Vertex.getEdgeValue() twice
我正在尝试在 giraph 中实现 Spinner 图分区算法。
在第一步中,我的程序向给定的输入图添加边,使其成为一个无向图,并且每个顶点都选择一个 运行dom 分区。 (此分区整数存储在 VertexValue
中)在此初始化步骤结束时,每个顶点向所有输出边发送一条消息,其中包含顶点 ID (a LongWritable
) 和顶点选择的分区.
一切正常。现在在我遇到问题的步骤中,每个顶点迭代接收到的消息并将接收到的分区保存在相应边的 EdgeValue
中。
(VertexValue
在 Vertex<I,V,E>
中是 V
,EdgeValue
在 Edge<I,E>
中是 E
)
以下是我的代码的重要部分:
包装器 类:
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
方法(运行是一个Random
对象):
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));
}
错误发生步骤中的compute
方法:
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();
}
但是,当我使用例如
遍历边缘时
for(Edge<LongWritable, EdgeValue> e : vertex.getEdges())
或通过
vertex.getEdgeValue(someVertex)
然后返回的 EdgeValue
具有权重 -2
和分区 -1
(标准构造函数的默认值)
我的想法是什么可能导致错误:
getEdgeValue(new LongWritable(someLong))
可能不起作用,因为它与具有相同值的另一个 new LongWritable(someLong)
是不同的对象。但是,我已经看到它在 giraph 代码中使用,所以这似乎没有问题,只有 LongWritable
中存储的 long 似乎很重要。
(最可能的原因)Hadoop 序列化和反序列化以某种方式改变了我的 EdgeValue
对象。由于 Hadoop 适用于非常大的图形,因此它们可能不适合 RAM。为此,VertexValue
和 EdgeValue
必须实施 Writable
。然而,在在线检查了一些 giraph 代码之后,我以一种对我来说似乎正确的方式实现了 read()
和 write()
(以相同的顺序写入和读取重要字段)。 (我认为这与问题有某种联系,因为第二次调用返回的 EdgeValue
具有标准构造函数的字段值)
我也看了一点文档:
E getEdgeValue(I targetVertexId)
Return the value of the first edge with the given target vertex id, or null if there is no such edge. Note: edge value objects returned by this method may be invalidated by the next call. Thus, keeping a reference to an edge value almost always leads to undesired behavior.
但是,这不适用于我,因为我只有一个 EdgeValue
变量,对吗?
提前感谢所有花时间帮助我的人。 (我使用的是 hadoop 1.2.1 和 giraph 1.2.0)
在查看了更多 giraph 代码示例后,我找到了解决方案:Vertex.getEdgeValue()
方法基本上创建了 EdgeValue
的副本
的顶点。如果你改变对象它returns,它不会写这些改变
回磁盘。要在 EdgeValue
或 VertexValue
中保存信息,您必须使用 setVertexValue()
或 setEdgeValue()
。
我正在尝试在 giraph 中实现 Spinner 图分区算法。
在第一步中,我的程序向给定的输入图添加边,使其成为一个无向图,并且每个顶点都选择一个 运行dom 分区。 (此分区整数存储在 VertexValue
中)在此初始化步骤结束时,每个顶点向所有输出边发送一条消息,其中包含顶点 ID (a LongWritable
) 和顶点选择的分区.
一切正常。现在在我遇到问题的步骤中,每个顶点迭代接收到的消息并将接收到的分区保存在相应边的 EdgeValue
中。
(VertexValue
在 Vertex<I,V,E>
中是 V
,EdgeValue
在 Edge<I,E>
中是 E
)
以下是我的代码的重要部分:
包装器 类:
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
方法(运行是一个Random
对象):
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));
}
错误发生步骤中的compute
方法:
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();
}
但是,当我使用例如
遍历边缘时for(Edge<LongWritable, EdgeValue> e : vertex.getEdges())
或通过
vertex.getEdgeValue(someVertex)
然后返回的 EdgeValue
具有权重 -2
和分区 -1
(标准构造函数的默认值)
我的想法是什么可能导致错误:
getEdgeValue(new LongWritable(someLong))
可能不起作用,因为它与具有相同值的另一个new LongWritable(someLong)
是不同的对象。但是,我已经看到它在 giraph 代码中使用,所以这似乎没有问题,只有LongWritable
中存储的 long 似乎很重要。(最可能的原因)Hadoop 序列化和反序列化以某种方式改变了我的
EdgeValue
对象。由于 Hadoop 适用于非常大的图形,因此它们可能不适合 RAM。为此,VertexValue
和EdgeValue
必须实施Writable
。然而,在在线检查了一些 giraph 代码之后,我以一种对我来说似乎正确的方式实现了read()
和write()
(以相同的顺序写入和读取重要字段)。 (我认为这与问题有某种联系,因为第二次调用返回的EdgeValue
具有标准构造函数的字段值)
我也看了一点文档:
E getEdgeValue(I targetVertexId)
Return the value of the first edge with the given target vertex id, or null if there is no such edge. Note: edge value objects returned by this method may be invalidated by the next call. Thus, keeping a reference to an edge value almost always leads to undesired behavior.
但是,这不适用于我,因为我只有一个 EdgeValue
变量,对吗?
提前感谢所有花时间帮助我的人。 (我使用的是 hadoop 1.2.1 和 giraph 1.2.0)
在查看了更多 giraph 代码示例后,我找到了解决方案:Vertex.getEdgeValue()
方法基本上创建了 EdgeValue
的副本
的顶点。如果你改变对象它returns,它不会写这些改变
回磁盘。要在 EdgeValue
或 VertexValue
中保存信息,您必须使用 setVertexValue()
或 setEdgeValue()
。