简单的Java Map / Reduce框架

时间:2011-03-10 13:24:40

标签: java mapreduce

有人能指出一个简单的,开源的Map / Reduce框架/ API for Java吗?似乎没有太多证据证明存在这样的事情,但其他人可能知道不同。

我能找到的最好的当然是Hadoop MapReduce,但这不符合“简单”标准。我不需要能够运行分布式作业,只需要让我在一个JVM中使用标准的Java5风格并发在多核机器上运行map / reduce-style作业。

写自己并不难,但我宁愿不必这样做。

10 个答案:

答案 0 :(得分:18)

您有结帐Akka吗?虽然akka实际上是一个基于分布式Actor模型的并发框架,但只需很少的代码就可以实现很多东西。将工作分成几部分非常容易,它可以自动充分利用多核机器,并能够使用多台机器来处理工作。与使用线程不同,我感觉更自然。

我有一个使用akka的Java map reduce example。这不是最简单的地图缩减示例,因为它利用了期货;但它应该让你大致了解所涉及的内容。我的地图缩小示例演示了几个主要内容:

  • 如何分工。
  • 如何分配工作:akka有一个非常简单的消息传递系统,以及一个工作分区,你可以配置它的日程安排。一旦我学会了如何使用它,我就无法停止。它非常简单灵活。我立即使用了所有四个CPU核心。这对于实施服务非常有用。
  • 如何知道工作何时完成且结果准备好处理:除非您已经熟悉Futures,否则实际上这部分可能是最困难和最容易理解的部分。您不需要使用Futures,因为还有其他选择。我刚刚使用它们是因为我想要一些更短的东西让人们犹豫不决。

如果您有任何疑问,StackOverflow实际上有一个很棒的akka​​ QA部分。

答案 1 :(得分:11)

我认为值得一提的是,这些问题是Java 8的历史。例如:

int heaviestBlueBlock =
    blocks.filter(b -> b.getColor() == BLUE)
          .map(Block::getWeight)
          .reduce(0, Integer::max);

换句话说:单节点MapReduce在Java 8中可用

有关详细信息,请参阅Brian Goetz's presentation about project lambda

答案 2 :(得分:10)

我使用以下结构

int procs = Runtime.getRuntime().availableProcessors();
ExecutorService es = Executors.newFixedThreadPool(procs);

List<Future<TaskResult>> results = new ArrayList();
for(int i=0;i<tasks;i++)
    results.add(es.submit(new Task(i)));
for(Future<TaskResult> future:results)
    reduce(future);

答案 3 :(得分:8)

我意识到这可能是事后的一点,但你可能想看一下JDK7的JSR166y ForkJoin类。

有一个支持JDK6的后端移植库,没有任何问题,所以你不必等到下一个千年才能使用它。它位于原始执行程序和hadoop之间,为当前JVM中的map reduce工作提供框架。

答案 4 :(得分:6)

几年前,当我买了一台8芯机器时,我为自己创造了一次性的一次性,但我对此并不十分满意。我从来没有像我希望的那样简单地使用它,并且内存密集型任务不能很好地扩展。

如果你没有得到任何真正的答案,我可以分享更多,但其核心是:

public class LocalMapReduce<TMapInput, TMapOutput, TOutput> {
    private int m_threads;
    private Mapper<TMapInput, TMapOutput> m_mapper;
    private Reducer<TMapOutput, TOutput> m_reducer;
    ...
    public TOutput mapReduce(Iterator<TMapInput> inputIterator) {
        ExecutorService pool = Executors.newFixedThreadPool(m_threads);
        Set<Future<TMapOutput>> futureSet = new HashSet<Future<TMapOutput>>();
        while (inputIterator.hasNext()) {
            TMapInput m = inputIterator.next();
            Future<TMapOutput> f = pool.submit(m_mapper.makeWorker(m));
            futureSet.add(f);
            Thread.sleep(10);
        }
        while (!futureSet.isEmpty()) {
            Thread.sleep(5);
            for (Iterator<Future<TMapOutput>> fit = futureSet.iterator(); fit.hasNext();) {
                Future<TMapOutput> f = fit.next();
                if (f.isDone()) {
                    fit.remove();
                    TMapOutput x = f.get();
                    m_reducer.reduce(x);
                }
            }
        }
        return m_reducer.getResult();
    }
}

编辑:根据评论,以下是没有sleep的版本。诀窍是使用CompletionService,它基本上提供了已完成Future的阻塞队列。

 public class LocalMapReduce<TMapInput, TMapOutput, TOutput> {
    private int m_threads;
    private Mapper<TMapInput, TMapOutput> m_mapper;
    private Reducer<TMapOutput, TOutput> m_reducer;
    ...
    public TOutput mapReduce(Collection<TMapInput> input) {
        ExecutorService pool = Executors.newFixedThreadPool(m_threads);
        CompletionService<TMapOutput> futurePool = 
                  new ExecutorCompletionService<TMapOutput>(pool);
        Set<Future<TMapOutput>> futureSet = new HashSet<Future<TMapOutput>>();
        for (TMapInput m : input) {
            futureSet.add(futurePool.submit(m_mapper.makeWorker(m)));
        }
        pool.shutdown();
        int n = futureSet.size();
        for (int i = 0; i < n; i++) {
            m_reducer.reduce(futurePool.take().get());
        }
        return m_reducer.getResult();
    }

我还会注意到这是一个非常精简的map-reduce算法,包括一个同时执行reduce和merge操作的reduce worker。

答案 5 :(得分:5)

我喜欢在Java中使用Skandium来实现并行性。该框架为具有共享内存的多核机器实现了某些并行模式(即Master-Slave,Map / Reduce,Pipe,Fork和Divide&amp; Conquer)。这种技术被称为“算法骨架”。模式可以嵌套。

详细说明有骷髅和肌肉。肌肉做实际的工作(分裂,合并,执行和条件)。骷髅代表并行度的模式,除了“While”,“For”和“If”,这在嵌套模式时很有用。

可以在框架内找到示例。我需要一点了解如何使用肌肉和骨骼,但在克服了这个障碍之后我真的很喜欢这个框架。 :)

答案 6 :(得分:3)

你看过GridGain吗?

答案 7 :(得分:3)

您可能需要查看功能4 Java的项目网站:http://f4j.rethab.ch/它在8之前引入了filter,map和reduce到java版本。

答案 8 :(得分:0)

在Hazelcast的v3.2中引入了MapReduce API(参见MapReduce API section in the docs)。虽然Hazelcast旨在用于分布式系统,但它在单节点设置中运行良好,而且相当轻巧。

答案 9 :(得分:0)

您可以尝试LeoTask:运行并行任务和结果聚合框架

它是免费的,开源的:https://github.com/mleoking/leotask

以下是显示其API的简要介绍:https://github.com/mleoking/leotask/blob/master/leotask/introduction.pdf?raw=true

它是一个轻量级框架,使用所有可用的CPU内核在一台计算机上运行。

它具有以下功能:

  • 自动&amp;并行参数空间探索
  • 灵活&amp;基于配置的结果聚合
  • 仅关注关键逻辑的编程模型
  • 可靠&amp;自动中断恢复

和实用程序:

  • 动态&amp;可复制的网络结构。
  • 与Gnuplot整合
  • 根据常见网络模型生成网络
  • DelimitedReader:一个复杂的读者,探索像数据库一样的CSV(逗号分隔值)文件
  • 基于Mersenne Twister算法的快速随机数生成器
  • 来自ImageJ项目的集成CurveFitter