2013年1月31日木曜日

Hadoopのタスクを任意の数のMapperで起動する


Hadoopを試してみて気づいたのが,やはり巨大ファイルに対しては効率が良いが,
若干処理が重いものを分散して行おうとすると全然ダメと言うこと.

設計思想を考えれば当たり前なんだけど,個人的には便利な分散処理システムとして使いたい.
具体的には,パラメータ設定を変えたシミュレーションを複数同時に走らせたい.

というわけで,かなり無理矢理にシミュレーションをHadoop上で走らせてみた.
やり方としては,
  1. シミュレーションの設定ファイルをDFS上に書き出す
  2. 設定ファイルを読み込んで,対応するシミュレーションを動かす
という処理をやってみた.

ちなみに,ファイル書き出しはこんな感じ


Configuration conf = new Configuration();
Path hdfsPath = new Path(filePath);
FileSystem fs = hdfsPath.getFileSystem(conf);
OutputStream os = fs.create(hdfsPath);
//パラメータファイルは一時ファイルとして,終了と同時に削除する
fs.deleteOnExit(hdfsPath);

OutputStreamWriter osw = new OutputStreamWriter(os);
for(String param:paramList){
 osw.append(param);
 osw.append("\n");
}
osw.flush();
os.close();




すると,

Kind% CompleteNum TasksPendingRunningCompleteKilledFailed/Killed
Task Attempts
map100.00%
100100 / 0
reduce100.00%
100100 / 0

こんな感じで,Mapが一つとか二つでしか起動してくれない.
これは,Hadoopがファイルを「適切な」大きさに直してしまうからである.
設定ファイルなんてたいした大きさじゃないから,どうしても2つくらいにしか分割してくれないわけだ.

というわけで,無理矢理ファイルの区切り位置を変えることで,好きな数のMapを走らせるようにしてみよう.

 

Configuration conf = new Configuration();
conf.setClass("ClassName", class, Scenario.class);
Job job = new Job(conf, "JobName");

//入力ファイルのPathを取得する
Path inputPath = new Path(inputFile.getAbsolutePath()); 
//対象ファイルサイズを取得
long length = inputPath.getFileSystem(conf).getFileStatus(inputPath).getLen(); 
//mapTaskNumは分割したいMap数.これで,1タスクあたりのファイルの区切りサイズを決定する
long splitSize = length/mapTaskNum; 
//最大でもそのサイズ以上にはならないようにタスクを区切る
FileInputFormat.setMaxInputSplitSize(job, splitSize); 


これを,job実行前に行っておけばよい.
これで,任意の数でMapを起動できる.



Kind% CompleteNum TasksPendingRunningCompleteKilledFailed/Killed
Task Attempts
map100.00%
300000300000 / 11
reduce100.00%
100100 / 0



分散し過ぎたw



2013年1月9日水曜日

Windows7にHadoop

Hadoopプログラミングをする上で,いちいちサーバにjarを持って行ってテストをするのは大変すぎるので,Windows上のEclipseでHadoopプログラムをデバッグすることを目指す.

インストール

まず,
https://ccp.cloudera.com/display/SUPPORT/CDH+Downloads
で,CDH3のtarを取得.
CDH3なのはサーバとバージョンを併せるため.

とりあえず,
Hadoop-0.20.2+923.421
をダウンロード.
Cygwinの/usr/local/libに展開.

$ cd /usr/local/lib
$ tar zxvf hadoop-0.20.2-cdh3u5.tar.gz
$ ln -s /cygdrive/c/Program\ Files\ \(x86\)/Java/jdk1.7.0_07/ jdk1.7
$ ln -s jdk1.7 java

Windowsの環境変数にHADOOP_HOMEを追加. Pathも追加.
HADOOP_HOME:C:\usr\cygwin\usr\local\lib\hadoop-0.20.2-cdh3u5
PATH:...;%HADOOP_HOME%\bin

hadoop/bin/hadoop-config.shに以下を追記
# the root of the Hadoop installation
if [ -z "$HADOOP_HOME" ]; then
  export HADOOP_HOME=`dirname "$this"`/..
else
  export HADOOP_HOME=$(cygpath -u "$HADOOP_HOME")
fi
hadoop-env.shにも以下を追記.
# The java implementation to use.  Required.
export JAVA_HOME=/usr/local/lib/java

Windowsではローカルモードでしか起動しないので,以下のように設定する.
conf/core-site.xml
<configuration>
    <property>
        <name>hadoop.tmp.dir</name>
        <value>C:\tmp\hadoop</value>
    </property>
</configuration>
conf/mapred-site.xml
<configuration>
    <property>
        <name>mapred.job.tracker</name>
        <value>local</value>
    </property>
</configuration>

Eclipseプラグイン

次に,Eclipseにプラグインを入れる. ここで,CDH3のHadoopにはEclipseのプラグインがないので,別途 hadoop-0.20.2.tar.gzをDLしてきて,
hadoop-0.20.2\contrib\eclipse-plugin\hadoop-0.20.2-eclipse-plugin.jar
をEclipseのpluginsにコピーする.

テスト

このページを参考に,
http://www.ne.jp/asahi/hishidama/home/tech/apache/hadoop/tutorial.html
WrodCounterをコピペ.
さらに,Starterとして以下を作成.inputFile.datには適当な文を入れておく.

public class Starter {
 static public void main(String[] args) throws Exception{
  WordCount.main(new String[]{"inputFile.dat", "output"});
 }
}

ここで,chmodがないよ,と怒られるので,Pathに以下を追加
Path ~;C:\usr\cygwin\bin
inputFile.dat
Hello World!
Hello Hadoop!
output/part-r-00000
Hadoop! 1
Hello 2
World! 1
無事成功.