我尝试使用 hadoop 分发计算。
我正在使用序列输入和输出文件,以及自定义可写文件。
输入是一个三角形列表,最大大小为 2Mb,但也可以小到 50kb 左右。 中间值和输出是自定义 Writable 中的 map(int,double)。 这是瓶颈吗?
问题是计算比没有hadoop的版本慢很多。 另外,将节点从 2 个增加到 10 个,并不会加快这个过程。
一种可能是我没有得到足够的映射器,因为输入量很小。 我做了测试改变
mapreduce.input.fileinputformat.split.maxsize
,但它变得更糟,而不是更好。
我在本地使用 hadoop 2.2.0,并在 amazon elastic mapreduce 上使用。
我是不是忽略了什么?或者这只是那种没有 hadoop 就应该完成的任务? (这是我第一次使用 mapreduce)。
你想看代码部分吗?
谢谢。
public void map(IntWritable triangleIndex, TriangleWritable triangle, Context context) throws IOException, InterruptedException {
StationWritable[] stations = kernel.newton(triangle.getPoints());
if (stations != null) {
for (StationWritable station : stations) {
context.write(new IntWritable(station.getId()), station);
}
}
}
class TriangleWritable implements Writable {
private final float[] points = new float[9];
@Override
public void write(DataOutput d) throws IOException {
for (int i = 0; i < 9; i++) {
d.writeFloat(points[i]);
}
}
@Override
public void readFields(DataInput di) throws IOException {
for (int i = 0; i < 9; i++) {
points[i] = di.readFloat();
}
}
}
public class StationWritable implements Writable {
private int id;
private final TIntDoubleHashMap values = new TIntDoubleHashMap();
StationWritable(int iz) {
this.id = iz;
}
@Override
public void write(DataOutput d) throws IOException {
d.writeInt(id);
d.writeInt(values.size());
TIntDoubleIterator iterator = values.iterator();
while (iterator.hasNext()) {
iterator.advance();
d.writeInt(iterator.key());
d.writeDouble(iterator.value());
}
}
@Override
public void readFields(DataInput di) throws IOException {
id = di.readInt();
int count = di.readInt();
for (int i = 0; i < count; i++) {
values.put(di.readInt(), di.readDouble());
}
}
}
只有 2MB 的数据,你不会从 hadoop 中获得任何好处。 Hadoop 就是关于大数据的。将 2MB 分配给 10 个节点比在单个节点上完成工作要花费更多的时间。真正的好处始于大量节点和海量数据。
如果处理真的那么复杂,您应该能够从使用 Hadoop 中获益。
小文件的常见问题是,Hadoop 将为每个文件运行一个 java 进程,这将产生开销,因为必须启动许多进程并减慢输出速度。在您的情况下,这听起来并不适用。您更有可能遇到相反的问题,即只有一个 Mapper 正在尝试处理您的输入,而此时您的集群有多大并不重要。使用输入拆分听起来是正确的方法,但由于您的用例是专门的并且明显偏离规范,您可能需要调整一些组件以获得最佳性能。
所以您应该能够从 Hadoop Map Reduce 中获得您正在寻求的好处,但它可能需要大量调整和自定义输入处理。
也就是说,MapReduce 很少(从不?)会比专门构建的解决方案更快。它是一个有用的通用工具,因为它可用于分发和解决许多不同的问题,而无需为每个问题编写专门构建的解决方案。
所以最后我想出了一种方法,不将中间值存储在可写对象中,只存储在内存中。这样速度更快。 但是,在这个用例中,非 hadoop 解决方案仍然是最好的。