4

MapReduce で実行される操作が交換可能かつ結合的でない場合、コンバイナーをレデューサーと同じにすることはできません。

たとえば、平均値を計算する場合、コンバイナーはキーの値を合計し、リデューサーは合計してから、その合計をそのキーの値の総数で割ります。コンバイナのコードはわずかに変更されています。コンバイナーとリデューサーの両方に同じクラスを使用し、現在のタスクがコンバイナーかリデューサーかを判断できるコードを用意できるとしたら? レデューサーであることがわかった場合は、合計をカウントで除算します。

このようなもの:

protected void reduce(Text keyIn, Iterable<PairWritable> valuesIn,
      Context context)
  throws IOException, InterruptedException {
    double sum = 0.0d;
    long count = 0l;

    for (PairWritable valueIn : valuesIn) {
      sum += valueIn.getSum();
      count += valueIn.getCount();
    }

    if (THIS_IS_A_REDUCER) {
      sum /= count;
    }

    context.write(keyIn, new PairWritable(sum, count));
  }

これを行うことは可能ですか?上記のコードの平和THIS_IS_A_REDUCERを何かに置き換えることはできますか?

タスクの試行 ID 文字列からタスクがマッパーかレデューサーかを判断できますが、コンバイナーとレデューサーの両方が同様の文字列パターンを持っているようです。

4

3 に答える 3

3

これは欠陥のある質問です。見つけたときはいつでも、タスクが呼び出す reduce() を区別する必要があります。コンバイナーを追加します。たとえば、あなたは書く

public static class Combine extends MapReduceBase implements Reducer<Text, Text, Text, Text> {
public void reduce(Text key, Iterator<Text> message, OutputCollector<Text, Text> output, Reporter reporter) throws IOException {}

public static class Reduce extends MapReduceBase implements Reducer<Text, Text, Text, Text> {
public void reduce(Text key, Iterator<Text> message, OutputCollector<Text, Text> output, Reporter reporter) throws IOException {}

main() で、次のように記述します。

conf.setReducerClass(Reduce.class);
conf.setCombinerClass(Combine.class);
于 2012-10-23T23:21:32.363 に答える
2

オブジェクトに問い合わせてContext、タスク ID を取得できると思います。次に、ID を取得すると、マッパー (コンバイナーを含む) の名前には「m」が含まれ、リデューサーの名前には「r」が含まれます。

タスク試行 ID を取得するには、.getTaskAttemptID()を使用します。これを使用するにはできるはずだと思いますがcontext.getTaskAttemptID()、確実にテストすることはできません。

于 2012-08-13T13:25:37.890 に答える