4
|
1 \chapter{評価実験}
|
|
2 本研究は、Jungleの分散環境上での性能を正しく評価するための実験を行う。
|
|
3 本章では実験の概要について述べる。
|
|
4 まず、本研究の目的について述べ、
|
|
5 次に、分散フレームワーク Aliceによる、本研究の分散機構を構成する方法について述べる。
|
9
|
6 次に、木構造上に立ち上げたJungleへ投入するタスクを制御するジョブスケジューラー、TORQUEについて述べる。
|
4
|
7 最後に、本実験の測定用プログラムについて述べる。
|
|
8 \section{実験目的}
|
13
|
9 Jungleは現在、Javaで実装されたものと、Huskellで実装されたものがある。
|
|
10 Java版は、処理速度が早く、よりスケーラビリティの高いデータベースの実装を目的に開発された。
|
10
|
11 対してHuskell版は、モダンな型システムと、型推論と型安全という特徴を生かし、信頼性の高データベースの実装を目的に開発された。
|
14
|
12 そして、これまでの研究で、Java版とHaskell版のJungleの分散性能を測定する実験が行われている。
|
|
13 分散性能測定実験では、それぞれJetty,Wrapというwebサーバーをフロントエンドに用いたWeb掲示板サービスを使用している。
|
10
|
14 Java版とHuskell版のWeb掲示板サービスをブレードサーバー上で実行される。
|
|
15 計測方法は、掲示板に対して読み込みと書き込みを行い、ネットワークを介してweighhttpで負荷をかける。
|
|
16 weighthttpの設定は、1スレッドあたり100並列のリクエストを、10スレッド分投入し、合計100万のリクエストを処理させる。
|
|
17 Java と Haskell の測定結果が表\ref{tab:compare}のようになった。
|
4
|
18
|
10
|
19 \begin{table}[!htbp]
|
|
20 \begin{center}
|
|
21 \begin{tabular}{|c||r|r|} \hline
|
|
22 測定 & Haskell & Java \\ \hline \hline
|
|
23 読み込み & 16.31 s & 53.13 s \\ \hline
|
|
24 書き込み & 20.17 s & 76.4 s \\ \hline
|
|
25 \end{tabular}
|
|
26 \end{center}
|
9
|
27
|
10
|
28 \caption{HaskellとJavaの比較}
|
|
29 \label{tab:compare}
|
|
30 \end{table}
|
9
|
31
|
10
|
32 Huskell 版は、 Java 版と比較して、読み込みで3,25倍、書き込みで 3.78倍 の性能差がでている結果となってしまった。
|
|
33 処理速度においてはHuskellよりも高いことを予想されていたのにもかかわらず、Java版がHuskell版よりも遅くなってしまった原因は、
|
|
34 測定時のWeb掲示板サービスのフロントエンドに、どちらもWebサーバーを用いているということが考えられる。しかも、その際は言語の問題から、異なる種類のWebサーバーを使用している。
|
|
35 これでは、この性能結果が、異なる言語で実装されたJungleの性能差によるものなのか、Webサーバーの性能差によるものなのかがわからない。
|
14
|
36 そこで、本研究ではJava版のJungleにおいて、Webサーバーを取り除いた、純粋なJungleの分散性能を測定するプログラムを実装した。
|
12
|
37 \section{実験概要}
|
14
|
38 Jungleの分散性能を測定するにあたり、複数台のJungleを通信させ、JungleからJungleに対する書き込みにかかる時間を計測する。複数台のJungleを分散させる為に、学内共用の仮想マシンを32台使用した。分散したJungle同士の通信部分には、当研究室で開発している分散フレームワークAliceの機能であるTopologyManagerを使用する。TopologyManagerの起動には、仮想マシン32台のうちの1台を使用する。
|
23
|
39 学科の仮想マシン31台上でそれぞれ1台ずつJungleを立ち上げ、ツリー型のトポロジーを構成する。そのうち16台のJungleに対して100回ずつデータを書き込む。子ノードのJungleは、他のJungleで書き込まれたデータを自身に書かれたデータとmergeしていく。全ての子ノードのJungleでmergeされたデータは、最終的に親ノードのJungleのデータへmergeされていく。
|
24
|
40 本実験では、複数の子ノードにJungleに書き込まれたデータが最終的にルートノードのJungleのデータへmergeされ、書き込まれた時間を計測し、平均を取る。図\ref{fig:gaiyou} は本実験を図で表したものであり、31 台中 16 台の Jungle から書き込まれた データがルートノードの Jungle へ書き込まれる、一回あたりの時間を計測する。
|
13
|
41 \begin{figure}[htbp]
|
|
42 \begin{center}
|
|
43 \includegraphics[width=100mm]{./pic/gaiyou.pdf}
|
|
44 \end{center}
|
|
45 \caption{複数のjungleに書き込まれたデータがrootのjungleへ到達する時間を計測する}
|
|
46 \label{fig:gaiyou}
|
|
47 \end{figure}
|
|
48
|
|
49 \section{実験環境}
|
|
50 学科のKVM上の仮想マシンによる仮想クラスタ環境を用いて実験を行った。
|
|
51 分散環境上での実験を行うにあたり、他の利用者とリソースが競合しないよう、TORQUEジョブスケジューラーを利用している。
|
|
52 KVMと仮想マシンの性能はそれぞれ表\ref{tab:kvm}、表\ref{tab:vm}である。
|
|
53 \begin{table}[htbp]
|
|
54 \begin{center}
|
|
55 \begin{tabular}{|c||r|r|} \hline
|
|
56 マシン台数 & Haskell \\ \hline
|
|
57 CPU & 16.31 s \\ \hline
|
|
58 物理コア数 & 20.17 s \\ \hline
|
|
59 論理コア数 & \\ \hline
|
|
60 CPUキャッシュ & \\ \hline
|
|
61 Memory & \\ \hline
|
|
62 \end{tabular}
|
|
63 \end{center}
|
|
64
|
|
65 \caption{KVMの詳細}
|
|
66 \label{tab:kvm}
|
|
67 \end{table}
|
|
68
|
|
69 \begin{table}[htbp]
|
|
70 \begin{center}
|
|
71 \begin{tabular}{|c||r|r|} \hline
|
|
72 マシン台数 & Haskell \\ \hline
|
|
73 CPU & 16.31 s \\ \hline
|
|
74 物理コア数 & 20.17 s \\ \hline
|
|
75 仮想コア数 & \\ \hline
|
|
76 CPUキャッシュ & \\ \hline
|
|
77 Memory & \\ \hline
|
|
78 \end{tabular}
|
|
79 \end{center}
|
|
80
|
|
81 \caption{仮想クラスタの詳細}
|
|
82 \label{tab:vm}
|
|
83 \end{table}
|
|
84
|
4
|
85 \section{TORQUE Resource Manager}
|
14
|
86 分散環境上でのJungleの性能を測定するにあたり、VM31台にJungleを起動させた後、16台のJungleに対し、データを書き込むプログラムを動作させる。プログラムを起動する順番やタイミングは、TORQUE Resource Managerというジョブスケジューラーによって管理する。
|
4
|
87
|
|
88 TORQUE Resource Manager は、ジョブを管理・投下・実行する3つのデーモンで構成されており、
|
|
89 ジョブの管理・投下を担うデーモンが稼働しているヘッダーノードから、ジョブの実行を担うデーモンが稼働している計算ノードへジョブが投下される(図\ref{fig:torque} )。
|
14
|
90 \begin{figure}
|
4
|
91 \begin{center}
|
|
92 \includegraphics[width=100mm]{./pic/torque.pdf}
|
|
93 \end{center}
|
|
94 \caption{TORQUEの構成}
|
|
95 \label{fig:torque}
|
|
96 \end{figure}
|
|
97
|
|
98 ユーザーはジョブを記述したシェルスクリプトを用意し、スケジューラーに投入する。その際に、利用したいマシン数やCPUコア数を指定する。TORQUEは、ジョブに必要なマシンが揃い次第、受け取ったジョブを実行する。
|
14
|
99
|
|
100 今回作成した、ジョブに投入するためのシェルスクリプトを以下(ソースコード\ref{src:LogupdateTest.pl})に示す。
|
4
|
101
|
24
|
102 \begin{lstlisting}[frame=lrbt,label=src:LogupdateTest.pl,caption=本実験で投入するジョブスクリプト,numbers=left]
|
12
|
103 #!/bin/sh
|
|
104 #PBS -q jungle
|
|
105 #PBS -N LogUpdateTest
|
|
106 #PBS -l nodes=16,walltime=00:08:00
|
|
107
|
|
108 cd /mnt/data/jungle_workspace/Log
|
|
109 /usr/bin/perl /mnt/data/jungle_workspace/scripts/LogupdateTest.pl
|
|
110 \end{lstlisting}
|
|
111 6行目で指定されたディレクトリに移動し、7行目ではそのディレクトリで、指定した別の階層にあるperlスクリプトを実行している。
|
|
112
|
4
|
113 \newpage
|
|
114
|
12
|
115
|
11
|
116 \section{分散フレームワーク Alice による分散環境の構築}
|
16
|
117 分散させたJungleの通信部分を担うのが、当研究室で開発している並列分散フレームワークAlice[1]である。Aliceは、ネットワーク上の複数のサーバーノードにトポロジーを形成させ、通信する機能を提供する。今回扱うサーバーノードに学科の仮想マシン(VM)を用いる。
|
15
|
118 本研究では、分散環境上でのJungleの性能を確認する為、VM32台分のサーバーノードを用意し、それぞれで1台ずつJungle起動することで、分散させる。
|
16
|
119 %Jungleを起動したサーバーノード間の通信部分を、当研究室で開発している並列分散フレームワークAlice[1]にて再現する。
|
11
|
120
|
24
|
121 Aliceには、ネットワークのトポロジーを構成するTopologyManager[2]という機能が備わっている。TopologyManagerは以下のソースコード\ref{src:topologymanager}のように起動する。
|
|
122 \begin{lstlisting}[frame=lrbt,label=src:topologymanager,caption=TopologyManagerの起動方法,numbers=left]
|
|
123 % java -cp ../../build/libs/logupdateTest-1.1.jar alice.topology.manager.TopologyManager -conf ../../scripts/tree.dot -p 10000
|
|
124 \end{lstlisting}
|
|
125 -p オプションはトポロジーマネージャーが開くポートの番号、-conf オプションには トポロジーファイルであるtree.dotのパスを渡している。トポロジーファイルとは、どのようにトポロジーノードをつなげるかを記述したファイルである。AliceのTopologyManagerを使用する際は、どのようなトポロジーを形成したいかを決め、あらかじめトポロジーファイルを作成する必要がある。今回、31台のサーバーノードでツリートポロジーを形成するdotファイルを以下のソースコード\ref{src:treedot}のように記述した。
|
|
126 \begin{lstlisting}[frame=lrbt,label=src:treedot,caption=作成したトポロジーファイル,numbers=left]
|
|
127 digraph test {
|
|
128 node0 -> node1 [label="child1"]
|
|
129 node0 -> node2 [label="child2"]
|
|
130 node1 -> node0 [label="parent"]
|
|
131 node1 -> node3 [label="child1"]
|
|
132 node1 -> node4 [label="child2"]
|
|
133 node2 -> node0 [label="parent"]
|
|
134 node2 -> node5 [label="child1"]
|
|
135 node2 -> node6 [label="child2"]
|
|
136 node3 -> node1 [label="parent"]
|
|
137 node3 -> node7 [label="child1"]
|
|
138 node3 -> node8 [label="child2"]
|
|
139 node4 -> node1 [label="parent"]
|
|
140 node4 -> node9 [label="child1"]
|
|
141 node4 -> node10 [label="child2"]
|
|
142 node5 -> node2 [label="parent"]
|
|
143 node5 -> node11 [label="child1"]
|
|
144 node5 -> node12 [label="child2"]
|
|
145 node6 -> node2 [label="parent"]
|
|
146 node6 -> node13 [label="child1"]
|
|
147 node6 -> node14 [label="child2"]
|
|
148 node7 -> node3 [label="parent"]
|
|
149 node8 -> node3 [label="parent"]
|
|
150 node9 -> node4 [label="parent"]
|
|
151 node10 -> node4 [label="parent"]
|
|
152 node11 -> node5 [label="parent"]
|
|
153 node12 -> node5 [label="parent"]
|
|
154 node13 -> node6 [label="parent"]
|
|
155 node14 -> node6 [label="parent"]
|
|
156 }
|
|
157 \end{lstlisting}
|
|
158 また、31台のサーバーノードで形成するトポロジーファイルを自動で生成するプログラムを作成した。以下のソースコード\ref{src:treedot.rb}に示す。
|
|
159 \begin{lstlisting}[frame=lrbt,label=src:treedot.rb,caption=本実験で使用するトポロジーファイルを生成するプログラム,numbers=left]
|
|
160 def create_nodes(node_num)
|
|
161 (0..node_num - 1).map { |i|
|
|
162 i = "node" + i.to_s
|
|
163 }
|
|
164 end
|
|
165
|
|
166 def print_dot(connections)
|
|
167 puts "digraph test {"
|
|
168 connections.each { |connection|
|
|
169 print "\t"
|
|
170 print connection[0]
|
|
171 print " -> "
|
|
172 print connection[1]
|
|
173 print ' [label="' + connection[2] + '"]'
|
|
174 puts
|
|
175 }
|
|
176 puts "}"
|
|
177 end
|
|
178
|
|
179 node_num = ARGV[0].to_i
|
|
180 nodes = create_nodes(node_num)
|
|
181 connections = Array.new
|
|
182 nodes.each_with_index { |node, i|
|
|
183 parent = (i - 1) / 2;
|
|
184 child1 = 2 * i + 1;
|
|
185 child2 = 2 * i + 2;
|
|
186 if parent >= 0 then
|
|
187 connections << [nodes[i], nodes[parent], "parent"]
|
|
188 end
|
|
189 if child1 < node_num then
|
|
190 connections << [nodes[i], nodes[child1], "child1"]
|
|
191 end
|
|
192 if child2 < node_num then
|
|
193 connections << [nodes[i], nodes[child2], "child2"]
|
|
194 end
|
|
195 }
|
|
196 print_dot(connections)
|
|
197 \end{lstlisting}
|
|
198 %ここにrubyの説明を入れてもいい
|
|
199 TopologyManagerは、参加表明をしたサーバーノード(以下TopologyNode)を、トポロジーファイルの内容に従ってトポロジーを構成する。
|
|
200 TopologyManagerへの参加表明は、TopologyNode起動時に、TopologyManagerのIPアドレスとポート番号を指定すれば良い。
|
|
201
|
|
202 TopologyNodeはTopologyManagerに、誰に接続を行えばよいかを尋ねる。TopologyManagerは尋ねてきたTopologyNodeに順番に、接続先のTopologyNodeのIPアドレス、ポート番号、接続名を送り、受け取ったTopologyNodeはそれらに従って接続する。
|
11
|
203 この時、TopologyManager自身はVM0を用いて立ち上げる。
|
|
204 よって、TopologyManagerはJungleをのせたVM1からVM32、計VM31台分のサーバーノードを、木構造を形成するように采配する(図\ref{fig:topologymanager} )。
|
|
205
|
|
206 \begin{figure}[H]
|
|
207 \centering
|
25
|
208 \includegraphics[width=90mm]{pic/topologymanager5.pdf}
|
11
|
209 \caption{AliceによるJungleの木構造トポロジーの形成}
|
|
210 \label{fig:topologymanager}
|
|
211 \end{figure}
|
25
|
212 (図\ref{fig:topologymanager})の矢印の流れを以下に示す。
|
|
213 \begin{enumerate}
|
|
214 \item TopologyManagerがトポロジーファイルを読み込む。
|
|
215 \item TopologyNodeがTopologyManagerに接続先を尋ねる。
|
|
216 \item 接続先のTopologyNodeのIPアドレス、ポート番号、接続名を送り返す。
|
|
217 \item 受け取った接続先の情報を元に、トポロジーを形成する。
|
|
218 \end{enumerate}
|
11
|
219
|
|
220 %DataSegment CodeSegment
|
|
221 Aliceはタスクを行うCodeSegmentと、CodeSegmentで使用するデータを扱うDataSegmentによってプログラムを行うスタイルを取る。
|
|
222 CodeSegmentはDataSegmentが必要なデータを受け取り次第、タスクを行う。DataSegmentがデータを受け取る為には、そのDataSegmentを示すキーが必要である。
|
|
223
|
|
224 TopologyManagerによって構成されたトポロジーのサーバーノードには、それぞれ自分自身を示す文字列であるキーが存在する。
|
|
225 このキーは自身のサーバーノードのDataSegmentがデータを受け取る際に指定する必要がある。
|
|
226
|
|
227 たとえば、servernode0,servernode1,servernode2により、(図\ref{fig:LogupdateTree})のように木構造が構成されたとする。
|
|
228 \begin{figure}[H]
|
|
229 \centering
|
|
230 \includegraphics[width=100mm]{pic/LogupdateTree.pdf}
|
|
231 \caption{トポロジーの形成}
|
|
232 \label{fig:LogupdateTree}
|
|
233 \end{figure}
|
|
234 この時、servernode0はservernode1、servernode2に対して親にあたる。逆に、servernode1,servernode2はservernode0に対して子にあたる。よって、(図\ref{fig:LogupdateTree})に矢印の隣にかかれている文字列"parent","child 1","child 2"のようにキーを指定している。
|
|
235 servernode0からservernode1へデータを送りたい場合、”child 1”というキーを追加すればいい。
|
|
236 このように、データアクセスしたいサーバーノードのキーを追加することで、そのサーバノードのDataSegmentへデータアクセスすることができる。
|
|
237 他のサーバーノードのDataSegmentへデータアクセスする際には、アクセス先のサーバーノードのキーを追加すればいい。
|
|
238 %TreeOperationLog
|
|
239 トポロジー構成後、Jungle間の通信でのデータ形式にはTreeOperationLogを利用する。TreeOperationLogは、Jungleによるノードの編集の履歴などの情報が入っている。TreeOperationLogは、AliceのDataSegmentでも扱えるようシリアライズ化されたデータである。よって、Aliceによって構成されたネットワークトポロジーのサーバノード間でのデータのアクセスが可能になっている。
|
|
240 TreeOperationLogをAliceによって他のJungleへ送る。送信先のJungleでは、送られてきたTreeOperationLogを参照して送信元のJungleと同じノード編集を行う。こうして、Jungle間でのデータの同期を可能にしている。
|
|
241 \newpage
|
|
242
|
16
|
243 \section{測定用プログラムの実装}
|
|
244 これまで、本実験の概要、測定環境について説明し、次にTORQUEによるJungleへのプログラム投下方法と、Aliceによる分散通信部分の構築方法について説明した。次説では、本実験の手順と合わせて、今回実装した部分である、Jungleにデータを書き込むための機能と時間計測部分について解説する。
|
|
245 本実験において、木構造を形成した32台のうち、16台のJungleへデータを100回書き込むプログラムを作成した。また、複数の子ノードにデータをそれぞれ書き込み、最終的にrootノードへデータを書き込んでいく時間を計測する為の機能を、新たにAliceに実装した。
|
20
|
246 以下のソースコード \ref{Logupdate}は、実装したテストプログラムの起動部分である。
|
4
|
247
|
20
|
248 \lstinputlisting[frame=lrbt, label=Logupdate, caption=測定用プログラムの起動部分,numbers=left]{./plsource.txt}
|
|
249
|
|
250 1行目で本実験のネットワークトポロジーを形成するためtopokogymanagerの起動を行なっている。\$nodesはVM0~VM31台の、合計32台の仮想マシンを表し、TopologyManagerはVM0に起動する。
|
16
|
251 -p オプションはTopologyManagerが開くポートの番号、-confオプションには dot ファイルのパスを渡している。ポート番号はAliceのより記述された並列分散プログラムの起動時に渡す必要がある。
|
|
252 dot ファイルには、トポロジーをどのように構成するかが書かれている。dotファイルを読み込んだAliceのTopologyManagerに対して、サーバーノードは誰に接続を行えばよいかを尋ねる。TopologyManagerは尋ねてきたサーバーノードに対してノード番号を割り振り、dotファイルに記述している通りにサーバーノードが接続を行うように指示をだす。
|
|
253 -showTime オプションは、今回Aliceに実装した機能である。--showTime オプションをつけることで、出力される結果に、子ノードのJungleからの書き込みがrootノードのJungleへ到達し、書き込みが終了したときの時間が表示されるようになる。
|
24
|
254 4行目では、Jungleを起動している。このとき、-host でTopologyManagerのIPアドレスを渡し、-portでTopologyManagerのポート番号をしている。TopologyManagerのIPアドレスとポート番号を渡すことで、TopologyManagerへ参加表明をしている。
|
25
|
255 10行目では、4行目と同様Jungleを起動しているが、今回実装した-writeオプションと-countオプションをつけている。
|
16
|
256 -writeオプションは、Jungleにデータを書き込む機能をつけることができる。
|
|
257 -countオプションは、何回データを書き込むかを指定することができる。隣に引数をつけることで、回数を設定できる。本実験では、16台のJungleで、100回データを書き込むよう設定する。
|
|
258 すなわち、TopologyManagerに1台、writeモードで立ち上げるJungleに16台使た後、残りの15台はそのままJungleを起動させている。
|
|
259 このスクリプトは、TORQUEによって各サーバーノードへ投入され、実行される。
|
|
260 %データを複数書き込む機能は、Jungleを立ち上げる際に-writeオプションと-countオプションをつけることで搭載される。
|
12
|
261 %Aliceのコードを参照する限り、TopologyManagerが起動した時から、終了するまでの間で時間を取得している。
|
17
|
262 %この図だと末端の子ノードからのみ書き込まれているように見える。実際は1~16の様々な場所にあるノードから書き込む。 |