S-JIS[2010-03-02/2010-03-19] 変更履歴

Hadoop Mapper

HadoopのMapperクラスについて。
(チュートリアルではMapperのクラス名はMapだが、java.util.Mapと紛らわしいな(苦笑))

  • Hadoop APIドキュメントのMapper

Mapperの概要

Mapperは、入力をキーと値の組に分解(マッピング?)する。
(Reducerは、このキー毎に値を演算(たいていは集計)する)

Mapperの出力は、Combinerが指定されていればCombinerに渡されることがある。
Reducerが指定されていれば、Reducerに渡される。
Reducerが0個であれば、直接OutputFormatに渡される。


Mapperの出力

チュートリアルでは、値の出力は以下の様にコーディングされている。

	public static class Map extends Mapper<LongWritable, Text, Text, IntWritable> {
		private final static IntWritable one = new IntWritable(1);
		private Text word = new Text();

		@Override
		protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
			String line = value.toString();
			StringTokenizer tokenizer = new StringTokenizer(line);
			while (tokenizer.hasMoreTokens()) {
				word.set(tokenizer.nextToken());
				context.write(word, one);
			}
		}
	}

Strutsやサーブレットプログラミングで“MTセーフ”に敏感になっている身としては、変数wordがフィールドに宣言されているのでマルチスレッドセーフになっていないのが気になる。
が、チュートリアルがこうなっているのだから、きっとMapperはマルチスレッドでは呼ばれないのだろう。


もうひとつ、context.write()にwordインスタンスをそのまま渡しているのも気になる。
内部でインスタンスを保持していたら、word.set()を呼ぶと保持している値が変わってしまうから。

context.write()の中身は、Reducerの個数で異なる。
Reducerが1個以上の場合はMapTask.NewOutputCollectorのwrite()が呼ばれるが、シリアライズされる(wordのクラスであるTextのwrite()メソッドが呼ばれる)ので、インスタンスを直接保持するような事はしていないから大丈夫。

Reducerが0個の場合は直接OutputFormatに渡される。
TextOutputFormatではファイルストリームに出力しているので大丈夫。
TableOutputFormatではインスタンスのコピーを作って保持しているので大丈夫。


Mapperの種類

Mapper(Hadoop0.20.1)には以下のようなクラスがある。
自分でマッパーを作る際には、MapperかTableMapper辺りを親クラスに使うのが普通だと思う。

クラス名 入力型 出力型 説明
KEYIN VALIN KEYOUT VALOUT
org.apache.hadoop.mapreduce.
Mapper
任意 任意 任意 任意 入力のキーと値をそのまま出力する。
→チュートリアル・サンプル
org.apache.hadoop.mapreduce.lib.map.
InverseMapper
任意 任意 VALIN KEYIN 入力のキーと値を入れ替えて出力する。
すなわち、出力キーは入力の値、出力値は入力のキーとなる。
org.apache.hadoop.mapreduce.lib.map.
TokenCounterMapper
Object
(未使用)
Text Text IntWritable 入力値をトークンに分割して、トークンをキー、「1」を値として出力する。
つまりはチュートリアルWordCountのMapと全く同じ。

→HBase関連のMapper


Mapperの個数

実行時にいくつのMapper(MapTask)が作られるのかは、InputFormat#getSplits()によって決まる。[2010-03-19]
(getSplits()は、処理しやすい単位に入力を分割して、処理単位(処理範囲・InputSplit)のリストを返す)

TextInputFormatなら、ファイルの個数やファイルサイズに応じて分割してくれる。
HBaseのTableInputFormatなら、テーブルのリージョン(領域)に応じて分割してくれる。

→Reducerの個数


Hadoop APIへ戻る / Hadoop目次へ戻る / Java目次へ行く / 技術メモへ戻る
メールの送信先:ひしだま