view presen/sample.markdown @ 182:a4c6184d3e22

minor change
author Nozomi Teruya <e125769@ie.u-ryukyu.ac.jp>
date Wed, 07 Feb 2018 09:18:50 +0900
parents 38d95e434fbc
children b62fc3a499f9
line wrap: on
line source

title: 分散フレームワークChristieの設計
author: 照屋のぞみ  

# 研究目的(1/2)
* 当研究室が開発している並列分散フレームワークAliceではスケーラブルな分散プログラムを信頼性高く記述できる環境を実現する
* ここで言う信頼性とは定められた環境下で安定して仕様に従った動作を行うことを指す
    * 仕様の記述のしやすさ、可読性、拡張時に仕様変更を抑えられるかも含む
* スケーラビリティとはサービス利用者が増加したとき単純にノードを追加するだけで線形に性能を向上させる能力

# 研究目的(2/2)
* 本研究では、Aliceの通信の信頼性を高めるためにNAT越えの機能設計を提案する
* そしてその実現にはAliceの再設計が必要であることを示す
* Aliceの問題点を整理し、得られた知見をもとに分散フレームワークChristieの設計を行う


# 目次
* Aliceの概要
* AliceのNAT越え
* Aliceの問題点
* Christieの設計
* 他フレームワークとの比較
* まとめ
* 今後の課題




# Data Segment と Code Segment
* Aliceではデータを **Data Segment(DS)** 、タスクを **Code Segment(CS)** という単位に分割して依存関係を記述することでプログラミングを行う。
* CSはInput DS(入力されるDS)とOutput DS(出力されるDS)を持つ。
* CSはkeyで指定されたDSが揃うと実行されるという性質を持つ。
![opt](./images/dsandcs.svg){:width="50%"}

# CodeSegmentの依存関係
* データの依存関係にないCSは並列実行される
* データの依存関係がある場合は Input DS が揃うと順に実行される
* DSはCSに専有されるためロックの記述を必要としない
![opt](./images/dsandcs2.svg){:width="60%"}

# Data Segment と CodeSegment
* AliceはJavaで実装されており、DSはJava-Object、CSはRunnableに相当する
* ユーザーが記述する際には CodeSegment.class を継承することでDSを操作するためのAPIを利用して依存関係を記述することができる。

# Data Segment Manager
* DS の集合体であるデータベースを Alice では **DS Manager(DSM)** と呼ぶ。  
* DSM 内の DS には対応する String型のkey が存在し、 DSM 名と key を指定しすることで DS の保存、取得を行う。
![opt](./pictures/key.svg){:width="50%"}

# Data Segment Manager
* Local DSM … 各ノード固有のデータベース
* Remote DSM … 他のノードのLocal DSMのproxy。接続しているノードの数だけ存在する。
* Remote DSMに書き込むと対応するノードのLocalDSMに書き込まれる
* Remote DSMにはString型のDSM keyを指定してアクセスする
![opt](./pictures/newDSM.svg){:width="50%"}

# Data Segment API 
* DSの取得
    * take/peek  
* DSの追加
    * put/update
* DSの転送
    * flip

# Code Segmentの記述例
* take/peekをするにはcreate/setKeyメソッドを使う
* *create* でインプットDGのRecieverを作り、*setKey* でReceiverにインプットとなるkeyを指定
* データをReceiverから取り出す際は *asClass()* で型を指定
* CSを生成し待ち合わせを指定するにはCSをnewする
```java
public class TestCodeSegment extends CodeSegment { 
    private Receiver input = ids.create(CommandType.TAKE);
    
    public TestCodeSegment() {
        input.setKey("count");
    }
    
    @Override
    public void run() {
        int count = input.asClass(Integer.class);
        System.out.println("data = " + count);
        
        new TestCodeSegment();
        
        ods.put("count", count);
    }
}
```

# Computation と Meta Computation
* 分散計算にはアルゴリズムの他に、以下のような処理が必要である。
	* 分散トポロジーの構成
	* 通信の切断・再接続時の処理
	* データの圧縮を含む表現形式の選択
    * NATなどのネットワークの詳細

* Aliceでは、これらをMeta Computationと呼ぶ。
* Meta ComputationもCS/DSによって記述される。
![opt](./pictures/metaCSDS.svg){:width="50%"}

# AliceのMeta Computation - Topology Manager
* Topology Manager
	* ノード間の接続管理やトポロジーの構成管理行うMeta Computation
	* Static Topology Manager...参加ノード数の決まったトポロジーをファイルに記述
    * Dynamic Topology Manager...可変長のノードに対応し、修復も行う 
![opt](./pictures/connect.svg){:width="50%"} 

# AliceのMeta Computation - 圧縮
* 圧縮したデータの伸長と圧縮したままの転送を同時に行いたい
* DSは内部に圧縮・非圧縮の複数の形式を複数もつことができる
![opt](./pictures/compress.svg){:width="80%"} 

# AliceのMeta Computation - 圧縮
* 圧縮の指定には宛先DGM keyに"compressed"とつけるだけでよい
`put("compressedRemoteDGM", "key", data)`
* 伸長も *asClass()* した際に自動でされる
* コードの変更が抑えて圧縮・非圧縮が切り替えられる

# AliceのNAT越え
* NATを越えたノード間通信は分散処理の課題である
* Aliceではトポロジー管理がアプリケーションから分離しているため、コードを大きく変更しなくとも複数のTopology Managerを立ち上げることでNAT越えが可能
![opt](./pictures/overNAT.svg){:width="70%"}

# 複数のTopology Managerへの対応
* この機能を実現するにはノードに割り当てられたnodeNameの衝突を避けなければならない
* 通常のLocal DSMとは別にTopology ManagerごとのLocal DSMを作成しnodeNameを管理
* Tpology Manager/Nodeの働きはそのままに、指定するLocal DSMを変えるだけでTopology Managerの複数対応が可能  
![opt](./pictures/somehostname2.svg){:width="50%"}


# Aliceの問題点 - LocalDSMを複数立ち上げられない
* AliceではDSMを管理するクラスがstaticで書かれていたためLocal DSMを複数立ち上げることができない
* このstaticを抜くにはAliceのコード全体を大きく変更しなければならない
* 現状ではNAT越えのMeta Computationの追加が困難
* 複数インスタンスを立ち上げての分散プログラムのテストが書けない
* 再設計の必要がある

# Aliceの問題点 - APIシンタックスの分離
* setKeyは記述場所が決まっておらず、待ち合わせを行っているCSの外からも呼べる
    * どのkeyを待っているのか不明なCSが生まれてしまう
* setKeyではkeyを動的に指定することができる
    * どんな処理を行っているかわかりづらい
    * 対応するput箇所も修正しなければならない

# Aliceの問題点 - APIシンタックスの分離
* setKeyは全てのcreateが終わった最後に呼ばなければならない
* このように交互に書くと実行時データを取り出すときにNullPointerExeptionになる
```java
class TestCG extends CodeSegment{
    private Receiver input1;
    private Receiver input2;

    public TestCG() {
        input1 = ids.create(CommandType.TAKE);
        input1.setKey("hoge");
        input2 = ids.create(CommandType.TAKE);
        input2.setKey("huga");
    }
}
```

# Aliceの問題点 - APIシンタックスの分離
![opt](./pictures/nullpo.svg){:width="60%"}


# Aliceの問題点 - 型が推測できない
* Input DSをReceiver型でcreateするため、どの型のデータを待っているのかわからない
* しかしReceiverからデータを取り出すにはasClass()で型を指定する必要がある
* 型をDSをputした箇所までコードをたどる必要がある

# Aliceの問題点 - まとめ
* 以下の問題がAliceの信頼性・拡張性を下げている
    * Local DSMを複数立ち上げられないため、Topology Managerの拡張やテストが困難
    * インプットAPIが分離しているためCSでどんな処理が行われているかわかりづらい
    * setKeyの記述順序や型を気にしてプログラミングをしなくてはならない
* これらを踏まえフレームワークChristieを設計する

# Christie - 基本設計(1)
* Javaで実装される
* 処理の単位にCode Gear(CG)/ Data Gear(DG) という名称を用いる
* Code Gear Manager(CGM)という機構がData Gear Manager(DGM)を管理

# Christie - 基本設計(2)
* CGM同士はThreadPoolを共有
    * ThreadPool...CPUに合わせた並列度でキューに入ったスレッドを順次実行していく実行機構
    * ThreadPoolが増えるとCPUのコア数に合わない量のスレッドを管理することになり、並列性が下がる    
* CGM同士はCGMのリストを共有
    * メタ計算で全てのCGMにアクセス可能
![opt](./pictures/ChristieClass.svg){:width="60%"}

# Christie -  基本設計(2) DGMの複数立ち上げ
* ChristieではCGMを2つ生成すればLocalDGMも2つ作られる
    * NAT越えなどの機能拡張に対応可能
* 複数のLocalDGM同士のやりとりは、Remoteへの接続と同じようにRemoteDGMを介してアクセスする
    * 分散プログラムのローカルでのテストが可能になる
![opt](./pictures/DGM.svg){:width="50%"}

# Christie - 基本設計(3)
* CG を記述する際は Alice同様CodeGear.classを継承
* CGは *void run(CodeGearManager cgm)* を持ち、run メソッド内に処理を記述
    * run内で新たなCGを作るためのAPIにはCGM経由で呼び出す

# Christie - アノテーションを用いたインプット記述
* keyの指定にはJavaのアノテーションを用いる
* フィールドやメソッドに対して@から始まる属性を付与できる
    * @Override、@SuppressWarningsなど
    * コンパイル時にエラーを出せる
```java
@Take(”count”)
public DataGear<Integer> count = new DataGear<>();
```

# Christie - アノテーションを用いたインプット記述
* 独自アノテーションを定義できる
    * フィールドやメソッドなどターゲットを指定できる
    * アノテーションを保持できる範囲をRUNTIME、CLASS、SOURCEから指定できる
    * 引数をうけとることもできる

```java
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Take {
    String value();
}
```

# Christie - アノテーションを用いたインプット記述
* InputのためのDGをフィールドで宣言し、それに対してアノテーションでkeyを指定
* アノテーションからRUNTIMEで待ち合わせの処理を行う
* Takeの例
```java
@Take(”count”)
public DataGear<Integer> count = new DataGear<>();
```
* RemoteTakeの例
```java
@RemoteTake(dgmName="remote", key=”count”)
public DataGear<Integer> count = new DataGear<>();
```

# Christie - アノテーションを用いたインプット記述
* アノテーションから待ち合わせを行う処理にはJavaのreflectionAPIを使用
* 待ち合わせを開始するには、newしたあとCGMが持つsetupを行う
`cgm.setup(new TestCodeGear());`
* フィールドがnewされたあとでないとrefrectionAPIで取れない

# Christie - アノテーションを用いたインプット記述
![opt](./pictures/setup.svg){:width="70%"}

# Christie - アノテーションによるシンタックスの分離阻止
* アノテーションは必ずフィールドに付けなければならない
    * InputDGの生成とkeyの指定を一箇所に書ける
* アノテーションの内容はコンパイル時に決定される
    * 動的なkey指定を防ぐ

# Christie - 型を指定しないデータ取り出し
* InputDGを宣言する際には必ず型の指定が必要となるため、CG内で型を把握できる
* DataGearはJavaの総称型を用いて<>内に指定した型を受け取る
```java
@Take(”count”)
public DataGear<Integer> count = new DataGear<>();
```

# Christie - 型を指定しないデータ取り出し
* reflectionAPIを使えばアノテーションのついているフィールドの情報もとれる
* 型を判断できる
* 宣言された型は内部で保存され、ノード間通信でも保たれる
* AliceのasClass()と違い、getData()で型を指定せずにデータを取り出すことができる
```java
public class GetData extends CodeGear{ 
    @Take(”name”)
    public DataGear<String> name = new DataGear<>();
    
    @Override
    protected void run(CodeGearManager cgm) {
        System.out.println(”this name is : ” + name.getData());
    }
}
```

# Christie - まとめ
* CodeGearManagerというDGMの管理機構を作ったことでLocalDGM複数立ち上げが可能になり、NAT越えなどの機能拡張やテストをしやすくなった
* アノテーションを用いたことでDG生成とkey指定の分離問題を解決し、処理の見通しを良くした
* 型の整合性を保証することで信頼性が向上した

# Christieと他フレームワークの比較
* Akka、Hazelcastと比較してChristieの特徴を述べる
    * Akka ...Scala/Java向け分散フレームワーク
    * Hazelcast ...Java向け分散フレームワーク

# Christieと他フレームワークの比較 - Akka
* アクターモデル
    * アクターと呼ばれるオブジェクト同士が並列で非同期メッセージを送受信するモデル
* アクターは固有のアドレス持つ
    * ローカルアクターにもリモートアクターにもアドレス指定でメッセージを送受信
    * `akka://mySystem/user/supervisorActor/childActor`
* アクターはメールボックスというキューを持つ
    * 受け取ったメッセージをパターンマッチで順次処理
    * パターンマッチにはScalaのcase classを用いられる
![opt](./pictures/Akka.svg){:width="70%"}

# Christieと他フレームワークの比較 - Hazelcast
* キーと値の1対1でデータを管理するインメモリ・データグリッド
    * 複数のノードに分散させたデータを、仮想的な1つのメモリ空間に見せるモデル
    * プログラマがサーバを意識せずに共有のタプルスペースに対してデータをget/put
* 共有のタプルスペースに書き込むとマルチキャストで全サーバにデータが送られる
![opt](./pictures/Hazelcast.svg){:width="50%"}

# Christieと他フレームワークの比較 - 設計思想
* AkkaやHazelcastはロケーション透過性が高く、分散プログラムの煩雑な処理を抽象度を高めることで隠している
* Christieでは分散性を明示的に意識しながら記述できるためチューニングしやすい
* 通常計算とメタ計算に分けているため複雑さを下げている

# Christieと他フレームワークの比較 - 記述性
* アノテーションを使ったインプットの指定はAkkaやHazelcastにはない
* 複数のインプットを待ち合わせして処理を行いたい場合
    * Akkaは待ち合わせ処理をプログラマが書かなければならない
    * Christieでは複数のインプットを記述でき待ち合わせ処理が必要ない
* データの圧縮通信を指定したい場合
    * Akka、Hazelcastでは圧縮メソッドが用意されているため、それを用いて記述する
    * ChristieではDGMkeyの名前を変えるだけでメソッド呼び出しの記述が要らないため少ない変更で拡張が可能

# まとめ
* AliceのプロトコルやMeta Computationを説明し、TopologyManagerを用いたNAT越えの手法を示した
* Aliceの問題点を整理し、再設計の必要性を述べた
* LocalDGMの複数立ち上げを可能にし、テストや機能拡張がしやすい環境を整えた
* Christieではアノテーションを用いたAPIで信頼性の高い記述を実現した
* Christieを他のフレームワークと比較し、分散性を意識して記述できる特徴があることを示した

# 今後の課題
* DataGearのメタレイヤーへの移行
    * ユーザーがDataGear型ではなく任意の型でインプットを宣言できるようにする
    * getData()をせず直接宣言した変数を使う
* TopologyManagerの実装
    * Christie上にTopologyManagerを実装し、NAT越えが可能か確認する
* 実用性の検証
    * Aliceと同等の分散プログラムの記述性能があるか確認する
    * アノテーションの処理がオーバーヘッドになっていないか測定する

# 今後の課題
* Jungleとの統合
    * DGMはトランザクションを持たない
    * 当研究室で開発しているJungleデータベースはトランザクションや差分管理機能を持つ
    * Jungleと統合できればより信頼性の高いデータ操作ができる 
* GearsOSへの移行
    * 当研究室で開発しているCG/DGモデルのOS
    * モデル検査機構akasyaの搭載など、より信頼性の高い記述環境
    * 将来GearsOSの分散部分にChristieを移植できると良い

<style type="text/css">
<!--
*{
	font:nomal 100% 'PT Sans';
}

ul > li{
	list-style-type:disc;
}

.slide h1{
	text-align:left;
	color:#777777;
	font:bold 40px/1.13 'PT Sans', sans-serif;
	margin-bottom: 50px;
}

div#slide1 h1{
	text-align:left;
	color:#777777;
	font:bold 60px 'PT Sans', sans-serif;
	margin-bottom: 50px;
}

pre > code{
	font-family:'Droid Sans Mono', 'Courier New', monospace;
}

img[alt="opt"]{
	display: block;
	margin-left: auto;
	margin-right: auto;
}

img[alt="right"]{
	margin-right: 0;
}

table {
	margin-left: auto;
	margin-right: auto;
}

th {
    font-size: 120%;
}
-->
</style>