背景
EMR(Elastic MapReduce)でAMI3.X(Hadoop2.X)を使うと、同じインスタンス構成でも、時間がかかることがある。
原因
YARN
Hadoop2.Xのリソース管理は、従来の1.Xのスロットによる管理とは異なるYARNと呼ばれるコンテナを用いたリソース管理を用いる。
ざっくり説明すると、ノード(インスタンス)全体のリソース量(メモリサイズとCPU数)から、割り当てたコンテナ(タスク)が利用するリソース量(メモリサイズとCPU数)を
順に引いていき、ノードの残りリソースが足りなくなれば、コンテナが終了してノードのリソースが返却されるまで新しいコンテナを割り当てないようにする仕組み。
症状
ところがAWSのEMRにおいてAMI3.X系を使うと、同じ構成なのに完了するまでのに時間が掛かる。同時に実行されるコンテナ数(Mapperタスク数に相当)が少ないのが確認できる。
具体的に言うと、CPUのコア数が4つあるc3.xlargeにおいて、3つのコンテナしか実行されてないということが分かる。
AWS EMRの設定とログの比較
AWSの設定と実際の動作に差があり、問題が発生する。
AWSのドキュメント
http://docs.aws.amazon.com/ElasticMapReduce/latest/DeveloperGuide/TaskConfiguration_H2.htmlによると、
c3.xlargeには、マップのコンテナの消費リソースである、mapreduce.map.memory.mbは1408と設定されている。
c3.xlargeのノード全体のリソース量は、5632であるので、1408のちょうど4倍であり、ノードあたり4つのMapコンテナが起動して問題ないはず。
しかし、ログを確認すると、
... Assigned container ... capacity <memory:1536, vCores:1> on host ...
なんと、勝手に1536に増やされているのである。よって、結局3つのコンテナしか割り当てられることはないことになる。
その理由
詳しいことは分からないが、設定値を256MBの倍数で扱う必要があるところ、端数がでてしまう1408の設定値にEMRが設定しているところが問題なようだ。
ためしに後述する方法で、1280に設定したところ、問題なくコンテナのリソース量は1208MBとなることが、ログの上でも確認できた。
対策
対策は二種類ある。マップのコンテナのメモリの設定を小さくし、256の倍数の1280にするか、(c3.xlargeの場合だが)ノードのリソース量を1536の4倍の6144にするか。
追加するオプションは、
http://docs.aws.amazon.com/ElasticMapReduce/latest/DeveloperGuide/emr-plan-bootstrap.html#bootstrapPredefinedを使うとCLIの場合はそれぞれ、
--bootstrap-action s3://elasticmapreduce/bootstrap-actions/configure-hadoop \
--args -m,mapred.map.memory.mb=1280 \
と
--bootstrap-action s3://elasticmapreduce/bootstrap-actions/configure-hadoop \
--args -y,yarn.nodemanager.resource.memory-mb=6144 \
である(c3.xlargeの場合)。なお両方設定する意味はない。私は7.5GBあるc3.xlargeだから、それでもまだ余裕がある後者の方を選んだ。
さらに4つのコンテナが同時にちょうど1536MBを使い、6144MBになることさえ稀であると考えられる。
追記
2015/03/17: Amazonの今井さんから判明したと連絡を受けました。
YARNにおけるコンテナへのメモリアロケーションの割り当てユニット ありがとうございます〜。