view paper/final_main/chapter3.tex @ 24:bf55a5069bf1

fix
author suruga
date Mon, 19 Feb 2018 15:56:50 +0900
parents ae83bdf21518
children df67999ffb29
line wrap: on
line source

\chapter{評価実験}
本研究は、Jungleの分散環境上での性能を正しく評価するための実験を行う。
本章では実験の概要について述べる。
まず、本研究の目的について述べ、
次に、分散フレームワーク Aliceによる、本研究の分散機構を構成する方法について述べる。
次に、木構造上に立ち上げたJungleへ投入するタスクを制御するジョブスケジューラー、TORQUEについて述べる。
最後に、本実験の測定用プログラムについて述べる。
\section{実験目的}
Jungleは現在、Javaで実装されたものと、Huskellで実装されたものがある。
Java版は、処理速度が早く、よりスケーラビリティの高いデータベースの実装を目的に開発された。
対してHuskell版は、モダンな型システムと、型推論と型安全という特徴を生かし、信頼性の高データベースの実装を目的に開発された。
そして、これまでの研究で、Java版とHaskell版のJungleの分散性能を測定する実験が行われている。
分散性能測定実験では、それぞれJetty,Wrapというwebサーバーをフロントエンドに用いたWeb掲示板サービスを使用している。
Java版とHuskell版のWeb掲示板サービスをブレードサーバー上で実行される。
計測方法は、掲示板に対して読み込みと書き込みを行い、ネットワークを介してweighhttpで負荷をかける。
weighthttpの設定は、1スレッドあたり100並列のリクエストを、10スレッド分投入し、合計100万のリクエストを処理させる。
Java と Haskell の測定結果が表\ref{tab:compare}のようになった。

\begin{table}[!htbp]
\begin{center}
\begin{tabular}{|c||r|r|} \hline
  測定 & Haskell & Java \\ \hline \hline
  読み込み & 16.31 s & 53.13 s \\ \hline
  書き込み & 20.17 s & 76.4 s \\ \hline
\end{tabular}
\end{center}

\caption{HaskellとJavaの比較}
\label{tab:compare}
\end{table}

Huskell 版は、 Java 版と比較して、読み込みで3,25倍、書き込みで 3.78倍 の性能差がでている結果となってしまった。
処理速度においてはHuskellよりも高いことを予想されていたのにもかかわらず、Java版がHuskell版よりも遅くなってしまった原因は、
測定時のWeb掲示板サービスのフロントエンドに、どちらもWebサーバーを用いているということが考えられる。しかも、その際は言語の問題から、異なる種類のWebサーバーを使用している。
これでは、この性能結果が、異なる言語で実装されたJungleの性能差によるものなのか、Webサーバーの性能差によるものなのかがわからない。
そこで、本研究ではJava版のJungleにおいて、Webサーバーを取り除いた、純粋なJungleの分散性能を測定するプログラムを実装した。
\section{実験概要}
Jungleの分散性能を測定するにあたり、複数台のJungleを通信させ、JungleからJungleに対する書き込みにかかる時間を計測する。複数台のJungleを分散させる為に、学内共用の仮想マシンを32台使用した。分散したJungle同士の通信部分には、当研究室で開発している分散フレームワークAliceの機能であるTopologyManagerを使用する。TopologyManagerの起動には、仮想マシン32台のうちの1台を使用する。
学科の仮想マシン31台上でそれぞれ1台ずつJungleを立ち上げ、ツリー型のトポロジーを構成する。そのうち16台のJungleに対して100回ずつデータを書き込む。子ノードのJungleは、他のJungleで書き込まれたデータを自身に書かれたデータとmergeしていく。全ての子ノードのJungleでmergeされたデータは、最終的に親ノードのJungleのデータへmergeされていく。
本実験では、複数の子ノードにJungleに書き込まれたデータが最終的にルートノードのJungleのデータへmergeされ、書き込まれた時間を計測し、平均を取る。図\ref{fig:gaiyou} は本実験を図で表したものであり、31 台中 16 台の Jungle から書き込まれた データがルートノードの Jungle へ書き込まれる、一回あたりの時間を計測する。
  \begin{figure}[htbp]
    \begin{center}
        \includegraphics[width=100mm]{./pic/gaiyou.pdf}
    \end{center}
        \caption{複数のjungleに書き込まれたデータがrootのjungleへ到達する時間を計測する}
         \label{fig:gaiyou}
\end{figure}

\section{実験環境}
学科のKVM上の仮想マシンによる仮想クラスタ環境を用いて実験を行った。
分散環境上での実験を行うにあたり、他の利用者とリソースが競合しないよう、TORQUEジョブスケジューラーを利用している。
KVMと仮想マシンの性能はそれぞれ表\ref{tab:kvm}、表\ref{tab:vm}である。
\begin{table}[htbp]
\begin{center}
\begin{tabular}{|c||r|r|} \hline
  マシン台数 & Haskell  \\ \hline 
  CPU & 16.31 s  \\ \hline
  物理コア数 & 20.17 s  \\ \hline
  論理コア数 &   \\ \hline
  CPUキャッシュ & \\ \hline
  Memory & \\ \hline
\end{tabular}
\end{center}

\caption{KVMの詳細}
\label{tab:kvm}
\end{table}

\begin{table}[htbp]
\begin{center}
\begin{tabular}{|c||r|r|} \hline
  マシン台数 & Haskell  \\ \hline 
  CPU & 16.31 s  \\ \hline
  物理コア数 & 20.17 s  \\ \hline
  仮想コア数 &   \\ \hline
  CPUキャッシュ & \\ \hline
  Memory & \\ \hline
\end{tabular}
\end{center}

\caption{仮想クラスタの詳細}
\label{tab:vm}
\end{table}

\section{TORQUE Resource Manager}
分散環境上でのJungleの性能を測定するにあたり、VM31台にJungleを起動させた後、16台のJungleに対し、データを書き込むプログラムを動作させる。プログラムを起動する順番やタイミングは、TORQUE Resource Managerというジョブスケジューラーによって管理する。

TORQUE Resource Manager は、ジョブを管理・投下・実行する3つのデーモンで構成されており、
ジョブの管理・投下を担うデーモンが稼働しているヘッダーノードから、ジョブの実行を担うデーモンが稼働している計算ノードへジョブが投下される(図\ref{fig:torque} )。
  \begin{figure}
    \begin{center}
        \includegraphics[width=100mm]{./pic/torque.pdf}
    \end{center}
        \caption{TORQUEの構成}
         \label{fig:torque}
\end{figure}

ユーザーはジョブを記述したシェルスクリプトを用意し、スケジューラーに投入する。その際に、利用したいマシン数やCPUコア数を指定する。TORQUEは、ジョブに必要なマシンが揃い次第、受け取ったジョブを実行する。

今回作成した、ジョブに投入するためのシェルスクリプトを以下(ソースコード\ref{src:LogupdateTest.pl})に示す。

\begin{lstlisting}[frame=lrbt,label=src:LogupdateTest.pl,caption=本実験で投入するジョブスクリプト,numbers=left]
#!/bin/sh
#PBS -q jungle
#PBS -N LogUpdateTest
#PBS -l nodes=16,walltime=00:08:00

cd /mnt/data/jungle_workspace/Log  
/usr/bin/perl /mnt/data/jungle_workspace/scripts/LogupdateTest.pl
\end{lstlisting}
6行目で指定されたディレクトリに移動し、7行目ではそのディレクトリで、指定した別の階層にあるperlスクリプトを実行している。

\newpage


\section{分散フレームワーク Alice による分散環境の構築}
分散させたJungleの通信部分を担うのが、当研究室で開発している並列分散フレームワークAlice[1]である。Aliceは、ネットワーク上の複数のサーバーノードにトポロジーを形成させ、通信する機能を提供する。今回扱うサーバーノードに学科の仮想マシン(VM)を用いる。
本研究では、分散環境上でのJungleの性能を確認する為、VM32台分のサーバーノードを用意し、それぞれで1台ずつJungle起動することで、分散させる。
%Jungleを起動したサーバーノード間の通信部分を、当研究室で開発している並列分散フレームワークAlice[1]にて再現する。

Aliceには、ネットワークのトポロジーを構成するTopologyManager[2]という機能が備わっている。TopologyManagerは以下のソースコード\ref{src:topologymanager}のように起動する。
\begin{lstlisting}[frame=lrbt,label=src:topologymanager,caption=TopologyManagerの起動方法,numbers=left]
% java -cp ../../build/libs/logupdateTest-1.1.jar alice.topology.manager.TopologyManager -conf ../../scripts/tree.dot -p 10000
\end{lstlisting}
-p オプションはトポロジーマネージャーが開くポートの番号、-conf オプションには  トポロジーファイルであるtree.dotのパスを渡している。トポロジーファイルとは、どのようにトポロジーノードをつなげるかを記述したファイルである。AliceのTopologyManagerを使用する際は、どのようなトポロジーを形成したいかを決め、あらかじめトポロジーファイルを作成する必要がある。今回、31台のサーバーノードでツリートポロジーを形成するdotファイルを以下のソースコード\ref{src:treedot}のように記述した。
\begin{lstlisting}[frame=lrbt,label=src:treedot,caption=作成したトポロジーファイル,numbers=left]
digraph test {
	node0 -> node1 [label="child1"]
	node0 -> node2 [label="child2"]
	node1 -> node0 [label="parent"]
	node1 -> node3 [label="child1"]
	node1 -> node4 [label="child2"]
	node2 -> node0 [label="parent"]
	node2 -> node5 [label="child1"]
	node2 -> node6 [label="child2"]
	node3 -> node1 [label="parent"]
	node3 -> node7 [label="child1"]
	node3 -> node8 [label="child2"]
	node4 -> node1 [label="parent"]
	node4 -> node9 [label="child1"]
	node4 -> node10 [label="child2"]
	node5 -> node2 [label="parent"]
	node5 -> node11 [label="child1"]
	node5 -> node12 [label="child2"]
	node6 -> node2 [label="parent"]
	node6 -> node13 [label="child1"]
	node6 -> node14 [label="child2"]
	node7 -> node3 [label="parent"]
	node8 -> node3 [label="parent"]
	node9 -> node4 [label="parent"]
	node10 -> node4 [label="parent"]
	node11 -> node5 [label="parent"]
	node12 -> node5 [label="parent"]
	node13 -> node6 [label="parent"]
	node14 -> node6 [label="parent"]
}
\end{lstlisting}
また、31台のサーバーノードで形成するトポロジーファイルを自動で生成するプログラムを作成した。以下のソースコード\ref{src:treedot.rb}に示す。
\begin{lstlisting}[frame=lrbt,label=src:treedot.rb,caption=本実験で使用するトポロジーファイルを生成するプログラム,numbers=left]
def create_nodes(node_num)
  (0..node_num - 1).map { |i|
    i = "node" + i.to_s
  }
end

def print_dot(connections)
  puts "digraph test {"
  connections.each { |connection|
    print "\t"
    print connection[0]
    print " -> "
    print connection[1]
    print ' [label="' + connection[2] + '"]'
    puts
  }
  puts "}"
end

node_num = ARGV[0].to_i
nodes = create_nodes(node_num)
connections = Array.new
nodes.each_with_index { |node, i|
  parent = (i - 1) / 2;
  child1 = 2 * i + 1;
  child2 = 2 * i + 2;
  if parent >= 0 then
    connections << [nodes[i], nodes[parent], "parent"]
  end
  if child1 < node_num then
    connections << [nodes[i], nodes[child1], "child1"]
  end
  if child2 < node_num then
    connections << [nodes[i], nodes[child2], "child2"]
  end
}
print_dot(connections)
\end{lstlisting}
%ここにrubyの説明を入れてもいい
 TopologyManagerは、参加表明をしたサーバーノード(以下TopologyNode)を、トポロジーファイルの内容に従ってトポロジーを構成する。
 TopologyManagerへの参加表明は、TopologyNode起動時に、TopologyManagerのIPアドレスとポート番号を指定すれば良い。
 
TopologyNodeはTopologyManagerに、誰に接続を行えばよいかを尋ねる。TopologyManagerは尋ねてきたTopologyNodeに順番に、接続先のTopologyNodeのIPアドレス、ポート番号、接続名を送り、受け取ったTopologyNodeはそれらに従って接続する。
この時、TopologyManager自身はVM0を用いて立ち上げる。
よって、TopologyManagerはJungleをのせたVM1からVM32、計VM31台分のサーバーノードを、木構造を形成するように采配する(図\ref{fig:topologymanager} )。

\begin{figure}[H]
    \centering
    \includegraphics[width=100mm]{pic/topologymanager3.pdf}
    \caption{AliceによるJungleの木構造トポロジーの形成}
    \label{fig:topologymanager}
\end{figure}

%DataSegment CodeSegment
Aliceはタスクを行うCodeSegmentと、CodeSegmentで使用するデータを扱うDataSegmentによってプログラムを行うスタイルを取る。
CodeSegmentはDataSegmentが必要なデータを受け取り次第、タスクを行う。DataSegmentがデータを受け取る為には、そのDataSegmentを示すキーが必要である。

TopologyManagerによって構成されたトポロジーのサーバーノードには、それぞれ自分自身を示す文字列であるキーが存在する。
このキーは自身のサーバーノードのDataSegmentがデータを受け取る際に指定する必要がある。

たとえば、servernode0,servernode1,servernode2により、(図\ref{fig:LogupdateTree})のように木構造が構成されたとする。
\begin{figure}[H]
    \centering
    \includegraphics[width=100mm]{pic/LogupdateTree.pdf}
    \caption{トポロジーの形成}
    \label{fig:LogupdateTree}
\end{figure}
この時、servernode0はservernode1、servernode2に対して親にあたる。逆に、servernode1,servernode2はservernode0に対して子にあたる。よって、(図\ref{fig:LogupdateTree})に矢印の隣にかかれている文字列"parent","child 1","child 2"のようにキーを指定している。
servernode0からservernode1へデータを送りたい場合、”child 1”というキーを追加すればいい。
このように、データアクセスしたいサーバーノードのキーを追加することで、そのサーバノードのDataSegmentへデータアクセスすることができる。
他のサーバーノードのDataSegmentへデータアクセスする際には、アクセス先のサーバーノードのキーを追加すればいい。
%TreeOperationLog
トポロジー構成後、Jungle間の通信でのデータ形式にはTreeOperationLogを利用する。TreeOperationLogは、Jungleによるノードの編集の履歴などの情報が入っている。TreeOperationLogは、AliceのDataSegmentでも扱えるようシリアライズ化されたデータである。よって、Aliceによって構成されたネットワークトポロジーのサーバノード間でのデータのアクセスが可能になっている。
TreeOperationLogをAliceによって他のJungleへ送る。送信先のJungleでは、送られてきたTreeOperationLogを参照して送信元のJungleと同じノード編集を行う。こうして、Jungle間でのデータの同期を可能にしている。
\newpage

\section{測定用プログラムの実装}
これまで、本実験の概要、測定環境について説明し、次にTORQUEによるJungleへのプログラム投下方法と、Aliceによる分散通信部分の構築方法について説明した。次説では、本実験の手順と合わせて、今回実装した部分である、Jungleにデータを書き込むための機能と時間計測部分について解説する。
本実験において、木構造を形成した32台のうち、16台のJungleへデータを100回書き込むプログラムを作成した。また、複数の子ノードにデータをそれぞれ書き込み、最終的にrootノードへデータを書き込んでいく時間を計測する為の機能を、新たにAliceに実装した。
以下のソースコード \ref{Logupdate}は、実装したテストプログラムの起動部分である。

\lstinputlisting[frame=lrbt, label=Logupdate, caption=測定用プログラムの起動部分,numbers=left]{./plsource.txt}

1行目で本実験のネットワークトポロジーを形成するためtopokogymanagerの起動を行なっている。\$nodesはVM0~VM31台の、合計32台の仮想マシンを表し、TopologyManagerはVM0に起動する。
-p オプションはTopologyManagerが開くポートの番号、-confオプションには dot ファイルのパスを渡している。ポート番号はAliceのより記述された並列分散プログラムの起動時に渡す必要がある。
dot ファイルには、トポロジーをどのように構成するかが書かれている。dotファイルを読み込んだAliceのTopologyManagerに対して、サーバーノードは誰に接続を行えばよいかを尋ねる。TopologyManagerは尋ねてきたサーバーノードに対してノード番号を割り振り、dotファイルに記述している通りにサーバーノードが接続を行うように指示をだす。
-showTime オプションは、今回Aliceに実装した機能である。--showTime オプションをつけることで、出力される結果に、子ノードのJungleからの書き込みがrootノードのJungleへ到達し、書き込みが終了したときの時間が表示されるようになる。
4行目では、Jungleを起動している。このとき、-host でTopologyManagerのIPアドレスを渡し、-portでTopologyManagerのポート番号をしている。TopologyManagerのIPアドレスとポート番号を渡すことで、TopologyManagerへ参加表明をしている。
10行目では、4行目と同様jungleを起動しているが、今回実装した-writeオプションと-countオプションをつけている。
-writeオプションは、Jungleにデータを書き込む機能をつけることができる。
-countオプションは、何回データを書き込むかを指定することができる。隣に引数をつけることで、回数を設定できる。本実験では、16台のJungleで、100回データを書き込むよう設定する。
すなわち、TopologyManagerに1台、writeモードで立ち上げるJungleに16台使た後、残りの15台はそのままJungleを起動させている。
このスクリプトは、TORQUEによって各サーバーノードへ投入され、実行される。
%データを複数書き込む機能は、Jungleを立ち上げる際に-writeオプションと-countオプションをつけることで搭載される。
%Aliceのコードを参照する限り、TopologyManagerが起動した時から、終了するまでの間で時間を取得している。
%この図だと末端の子ノードからのみ書き込まれているように見える。実際は1~16の様々な場所にあるノードから書き込む。