web-dev-qa-db-ja.com

シンプルJava Map / Reduceフレームワーク

Java用のシンプルでオープンソースのMap/Reduceフレームワーク/ APIを誰かが指摘できますか?そのようなものが存在するという証拠はあまりないようですが、他の誰かが違うことを知っているかもしれません。

私が見つけることができる最高のものはもちろん、Hadoop MapReduceですが、それは「単純な」基準を満たしていません。分散ジョブを実行する機能は必要ありません。標準のJava5スタイルの同時実行性を使用して、単一のJVMでマルチコアマシンでmap/reduceスタイルのジョブを実行できるようにするだけです。

自分で書くのは難しいことではありませんが、そうする必要はありません。

49
skaffman

これらの問題はJava 8の時点での履歴であることに言及する価値があると思います。

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

つまり、単一ノードのMapReduceはJava 8)で利用可能です。

詳細については、 プロジェクトラムダに関するBrian Goetzのプレゼンテーション を参照してください。

11
Lukas Eder

Akka をチェックアウトしましたか? akkaは実際には分散アクタモデルベースの同時実行フレームワークですが、わずかなコードで簡単に多くのことを実装できます。作業を分割するのはとても簡単で、自動的にマルチコアマシンを最大限に活用し、複数のマシンを使用して作業を処理できます。スレッドを使用するのとは異なり、それは私にとってより自然に感じます。

Java map reduce example akkaを使用しています。futureを利用しているため、最も簡単なmap reduceの例ではありません。私のmap reduceの例が示すいくつかの主要な事柄があります:

  • 仕事を分ける方法。
  • 作業の割り当て方法:akkaには、本当に簡単なメッセージングシステムがあり、仕事のパーティショナーとして、スケジュールを構成できます。使い方を学んだら、やめられませんでした。とてもシンプルで柔軟です。私はすぐに4つのCPUコアをすべて使用していました。これは、サービスを実装するために本当に素晴らしいです。
  • いつ作業が完了し、結果を処理する準備ができているかを知る方法:これは、実際にFuturesに精通していない限り、実際に理解するのが最も難しくて混乱しやすい部分です。他のオプションがあるため、フューチャーを使用する必要はありません。人々がより短いものを欲しがるので、私はそれらを使用しました。

ご質問があれば、StackOverflowには実際に素晴らしいakka QAセクションがあります。

18
chaostheory

私は次の構造を使用します

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);
10
Peter Lawrey

これは事実の少し後かもしれませんが、JDK7の JSR166y ForkJoin クラスを見たいと思うかもしれません。

JDK6で問題なく動作するバックポートライブラリがあります。そのため、次の千年紀まで試してみる必要はありません。 raw executorとhadoopの間のどこかにあり、現在のJVM内でmap reduceジョブを処理するためのフレームワークを提供します。

8
Gareth Davis

数年前に8コアのマシンを手に入れたとき、私は自分のために1回限りのものを作成しましたが、それにはそれほど満足していませんでした。思ったほど簡単に使用できるとは思いませんでした。また、メモリを集中的に使用するタスクはうまく拡張できませんでした。

realの回答が得られない場合は、もっと共有できますが、その中心は次のとおりです。

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を使用することです。これは、本質的に、完了したFuturesのブロッキングキューを提供します。

 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();
    }

また、これは、reduce操作とmerge操作の両方を実行する単一のreduceワーカーを含む、非常に蒸留されたmap-reduceアルゴリズムであることに注意してください。

6
xan

Javaの並列処理に Skandium を使用するのが好きです。このフレームワークは、共有メモリを備えたマルチコアマシン向けの特定の並列処理パターン(つまり、マスタースレーブ、マップ/リデュース、パイプ、フォーク、分割統治)を実装しています。この手法は「アルゴリズムスケルトン」と呼ばれます。パターンはネストできます。

詳細には、骨格と筋肉があります。筋肉は実際の作業(分割、マージ、実行、および調整)を行います。スケルトンは、パターンをネストするときに役立つ「While」、「For」、および「If」を除き、並列処理のパターンを表します。

例はフレームワーク内にあります。筋肉と骨格の使い方を少し理解する必要がありましたが、このハードルを乗り越えた後、私はこのフレームワークが本当に好きです。 :)

5
Florian Pilz

GridGain をご覧になりましたか?

3
Costi Ciudatu

Functionals 4 JavaのプロジェクトWebサイトをご覧ください: http://f4j.rethab.ch/ フィルター、マップ、 8より前のJavaバージョンに減らします。

3
rethab

LeoTaskを試すことができます:並列タスク実行および結果集約フレームワーク

無料でオープンソースです: https://github.com/mleoking/leotask

そのAPIを示す簡単な紹介です: https://github.com/mleoking/leotask/blob/master/leotask/introduction.pdf?raw=true

これは、使用可能なすべてのCPUコアを使用して、単一のコンピューターで動作する軽量フレームワークです。

次の機能があります。

  • 自動および並列パラメータ空間探査
  • 柔軟な構成ベースの結果集約
  • キーロジックのみに焦点を当てたプログラミングモデル
  • 信頼性の高い自動割り込みリカバリ

およびユーティリティ:

  • 動的で複製可能なネットワーク構造。
  • Gnuplotとの統合
  • 一般的なネットワークモデルに従ったネットワーク生成
  • DelimitedReader:データベースのようなCSV(コンマ区切り値)ファイルを探索する洗練されたリーダー
  • Mersenne Twisterアルゴリズムに基づく高速乱数ジェネレーター
  • ImageJプロジェクトの統合されたCurveFitter
0
user4432445

MapReduce APIがHazelcast v3.2に導入されました(ドキュメントの MapReduce APIセクションを参照 )。 Hazelcastは分散システムでの使用を目的としていますが、単一ノードのセットアップでは完全に機能し、かなり軽量です。

0
skaffman