# HG changeset patch # User Tatsuki IHA # Date 1518460585 -32400 # Node ID 14bd1b466bcc0819d138b02e81caedd8d5478bb4 # Parent 3fddb8ee71ea49de1a3dbc44f3c92ee22d1db7c3 Update slide diff -r 3fddb8ee71ea -r 14bd1b466bcc slide/images/compareExamples.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/slide/images/compareExamples.svg Tue Feb 13 03:36:25 2018 +0900 @@ -0,0 +1,170 @@ + + + +Gnuplot +Produced by GNUPLOT 5.2 patchlevel 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + 200 + + + + + 400 + + + + + 600 + + + + + 800 + + + + + 1000 + + + + + 1200 + + + + + 1 + + + + + 2 + + + + + 4 + + + + + 8 + + + + + 16 + + + + + 32 + + + + + + + + + time(ms) + + + + + CPUs + + + + + twice + + + "gears_poweredge" + + + "gears_poweredge" + + + + + + "go_poweredge" + + + "go_poweredge" + + + + + + "openmp_poweredge" + + + "openmp_poweredge" + + + + + + + + + + + + + + + + + + diff -r 3fddb8ee71ea -r 14bd1b466bcc slide/slide.html --- a/slide/slide.html Tue Feb 13 02:23:41 2018 +0900 +++ b/slide/slide.html Tue Feb 13 03:36:25 2018 +0900 @@ -87,7 +87,7 @@ @@ -271,7 +271,7 @@

stub Code Gear

@@ -314,6 +314,11 @@
  • 操作(API)自体のCode Gear の型
  • +
  • __code next(…) は一種のクロージャであり、 引数で Code Gear を渡すことが出来る + +
  • typedef struct Queue<Impl>{
    @@ -343,7 +348,7 @@
       
  • 実装した Data Gear の生成は関数呼び出しで行われ、外から見るとInterface の型で扱われる
  • -
    Queue* createSingleLinkedQueue(struct Context* context) {
    +
    Queue* createSingleLinkedQueue(struct Context* context) {
         struct Queue* queue = new Queue(); // Allocate Queue interface
         struct SingleLinkedQueue* singleLinkedQueue = new SingleLinkedQueue(); // Allocate Queue implement
         queue->queue = (union Data*)singleLinkedQueue;
    @@ -361,39 +366,13 @@
     
     
    -

    Interface の実装例

    -
      -
    • SingleLinkedQueue の put 実装
    • -
    • 引数は Queue Interface の put 定義にあわせる
    • -
    • 第1引数は 実装対象の Data Gear の型になる
    • -
    • 第3引数の(…) は Output Data Gear を記述する -
        -
      • … は可変長引数のような扱いで、 継続先の Code Gear が複数の値をInput Data Gear とする可能性がある
      • -
      -
    • -
    - -
    __code putSingleLinkedQueue(struct SingleLinkedQueue* queue, union Data* data, __code next(...)) {
    -    Element* element = new Element();
    -    element->data = data;
    -    element->next = NULL;
    -    queue->last->next  = element;
    -    queue->last = element;
    -    goto next(...);
    -}
    -
    - - -
    -
    -

    Interface を利用した Code Gear の呼び出し

    • Interface を利用した Code Gear への継続は goto interface->method で行われる
    • ここでの interface は Interfaceの型で包んだData Gear、 method は実装した Code Gear に対応する
    -
    __code code1() { 
    +
    __code code1() { 
         Queue* queue = createSingleLinkedQueue(context);
         Node* node = new Node();
         node->color = Red;
    @@ -417,7 +396,7 @@
       
  • 呼び出すCode Gear の引数情報に合わせて引数に格納し、 実装された Code Gear へ継続する
  • -
    __code code1(struct Context *context) {
    +
    __code code1(struct Context *context) {
         Queue* queue = createSingleLinkedQueue(context);
         Node* node = &ALLOCATE(context, Node)->Node;
         node->color = Red;
    @@ -438,7 +417,8 @@
       
  • Interface を実装した Code Gear は Interface の定義から stub Code Gear の自動生成が可能である
  • -
    __code putSingleLinkedQueue(struct Context *context,struct SingleLinkedQueue* queue, union Data* data, enum Code next) {
    +
    __code putSingleLinkedQueue(struct Context *context,struct SingleLinkedQueue* queue,
    +                            union Data* data, enum Code next) {
         Element* element = &ALLOCATE(context, Element)->Element;
         element->data = data;
         element->next = NULL;
    @@ -474,7 +454,7 @@
             
    • SynchronizedQueue から Task を一つずつ取得し、実行する
    • Worker は CPU、 GPU の対応した数分生成する
    • -
    • Worker 毎に POSIX Therad などのスレッドを生成し、 Code Gear を実行する
    • +
    • Worker 毎に POSIX Therad などを生成し、それぞれのスレッドで Code Gear を実行する
  • SynchronizedQueue @@ -514,18 +494,12 @@
    -
    - message -
    -
    + message +
      -
    1. Task を Input Data Gear として
    2. - TaskManager の spawn を呼び出す -
    3. Task内の idgCountをチェックする
    4. - idgCount は待っているInput Data Gear のカウンタである - そのため、カウンタが0の場合 Input Data Gear が揃っていることになる -
    5. 揃っている場合、 Worker の Queue に
    6. - Task を送信する +
    7. Task を Input Data Gear としてTaskManager の spawn を呼び出す
    8. +
    9. Task が待っている Data Gear のカウンタである idgCount をチェックする
    10. +
    11. idgCount が0の場合 Data Gear が 揃っているので Worker の Queue に Task を送信する
    @@ -542,18 +516,15 @@
    -
    - message -
    -
    + message +
    1. Worker は Queue から Task を取得する
    2. -
    3. Worker の Context から
    4. - Task の Context へ入れ替える +
    5. Worker の Context からTask の Context へ入れ替える
    6. +
    7. Task に設定されている Code Gear を実行
    8. Task の Output Data Gear の書き出し
    9. -
    10. Task Context から
    11. - Worker の Context へ入れ替える +
    12. Task Context から Worker の Context へ入れ替える
    13. Worker は再び Queue から Task を取得する
    @@ -621,11 +592,25 @@
  • この記述を直接書くと Meta Data Gear である Context を直接参照しているため、ノーマルレベルでの記述では好ましくない
  • Task の設定は煩雑な記述であるが、並列実行されることを除けば通常の CbC の goto 文と同等である
  • そこで Context を直接参照しない並列構文、 par goto 構文を新たに考案した
  • + + + +
    +
    + +

    par goto 構文

    +
      +
    • par goto 構文を記述すると新しく Context を生成し、TaskManager を通して Worker に送信される
    • par goto 構文には引数として Input/Output Data Gear等を渡す
      • スクリプトによって Code Gear の Input/Output の数を解析する
    • +
    • Task は __exit に継続することで終了する +
        +
      • Gears OS は Output Data Gear 生成した時点で終了するため__exit に直接継続せずに Data Gear を書き出す処理に継続する
      • +
      +
    __code code1(Integer *integer1, Integer * integer2, Integer *output) {
    @@ -751,6 +736,9 @@
     
    • Twice は与えられた整数配列を2倍にする例題である
    • 並列実行の依存関係がなく、並列度が高い課題である
    • +
    • 要素数 2^27
    • +
    • CPU での実行時は 2^27 を 2^6 個に分割して Task を生成する
    • +
    • GPU での実行時は1次元の block 数を 2^15、 block 内の thread 数を 2^10 で展開
    @@ -759,9 +747,6 @@

    Twice の結果

      -
    • 要素数 2^27
    • -
    • CPU での実行時は 2^27 を 2^6 個に分割して Task を生成する
    • -
    • GPU での実行時は1次元の block 数を 2^15、 block 内の thread 数を 2^10 で展開
    • 1 CPU と 32 CPU では 約27.1倍の速度向上が見られた
    • GPU 実行は kernel のみの実行時間は32 CPU に比べて約7.2倍の速度向上、通信時間を含めると 16 CPU より遅い
    • 通信時間がオーバーヘッドになっている
    • @@ -816,6 +801,9 @@
      • 並列処理向けのソートアルゴリズム
      • 決まった2点間の要素の入れ替えをステージ毎に並列に実行し、 Output Data Gear として書き出し、次のステージの Code Gear の Input Data Gear とする
      • +
      • 要素数 2^24
      • +
      • CPU での実行時は 2^24 を 2^6 個に分割して Task を生成する
      • +
      • GPU での実行時は1次元の block 数を 2^14、 block 内の thread 数を 2^10 で展開
      @@ -824,9 +812,6 @@

      BitonicSort の結果

        -
      • 要素数 2^24
      • -
      • CPU での実行時は 2^24 を 2^6 個に分割して Task を生成する
      • -
      • GPU での実行時は1次元の block 数を 2^14、 block 内の thread 数を 2^10 で展開
      • 1 CPU と 32 CPU で約22.12倍の速度向上
      • GPU は通信時間を含めると 8 CPU の約1.16倍、 kernel のみの実行では 32 CPU の約11.48倍になった
      • 現在の Gears OS の CUDA 実装では Output Data Gear を書き出す際に一度 GPU から CPU へ kernel の結果の書き出しを行っているため、差がでてしまった
      • @@ -922,37 +907,6 @@
    -

    OpenMP との比較

    -
      -
    • OpenMP で Twice を実装し、速度比較を行った
    • -
    • OpenMP は 1CPU と 32CPU で約10.8倍の速度向上が見られた
    • -
    • 一方 Gears OS では約27.1倍と台数効果は高くなっている
    • -
    • しかし、 Gears OS は 1CPU の実行速度が OpenMP に比べて大幅に遅くなっている
    • -
    - -
    - message -
    - - -
    -
    - -

    Go 言語との比較

    -
      -
    • Go 言語でも OpenMP と同様に Twice を実装し、速度比較を行った
    • -
    • Go 言語は 1CPU と 32CPU で約4.33倍の速度向上が見られた
    • -
    • OpenMP と同様に台数効果自体は Gears OS が高いが、 1CPU での実行時間は Go 言語が大幅に速い
    • -
    - -
    - message -
    - - -
    -
    -

    まとめ

    • Gears OS の並列処理機構の実装を行った
    • @@ -968,24 +922,74 @@

      今後の課題

      • Gears OS の並列処理の信頼性の保証、チューニングを行う
      • +
      + + +
    +
    + +

    今後の課題

    +
    • Gears OS では検証とモデル検査をメタレベルで実現することで信頼性を保証する
      • 証明は CbC のプログラムを証明支援系の Agda に対応して行う。 並列処理の信頼性を保証するには SynchronizedQueue の証明を行う必要がある
      • モデル検査は CbC で記述された モデル検査器である akasha を使用して行う。 モデル検査の方針としては Code Gear の並列実行を擬似並列で実行し、全ての組合せを列挙する方法で行う
    • +
    + + +
    +
    + +

    今後の課題

    +
    • 現在の CUDA 実装では CPU、GPU 間のデータの通信コストがかかってしまうことが例題からわかった
      • Meta Data Gear に Data Gear が CPU、 GPU のどこで所持されているのかを持たせ、 GPU の Data Gear が CPU で必要になったときに始めてデータの通信を行う
    • -
    • OpenMP、 Goとの比較から、 Gears OS が 1CPU での動作が遅いということがわかった。 +
    + + +
    +
    + +

    今後の課題

    +
      +
    • OpenMP、 Go で Twice を実装し、 Gears OS の性能比較を行った
    • +
    • その結果、 Gears OS が 1CPU での動作が遅いということがわかった。
      • par goto 文を使用する度に Context を生成するため、 ある程度の時間がかかってしまう
      • モデル検査で par goto の Code Gear のフローを解析し、処理がかる場合は Context を生成せずに関数呼出しを行う等の最適化が必要
    + +
    + message +
    + +
    diff -r 3fddb8ee71ea -r 14bd1b466bcc slide/slide.md --- a/slide/slide.md Tue Feb 13 02:23:41 2018 +0900 +++ b/slide/slide.md Tue Feb 13 03:36:25 2018 +0900 @@ -103,7 +103,7 @@ - Gears OS ではメタ計算で Context を経由して Code/Data Gear にアクセスする ## stub Code Gear -- Data Gear にアクセスするにはContext を経由する +- Data Gear にアクセスするには Context から番号を指定して行う - だが、通常の Code Gear では Meta Data Gear である Context の参照は避ける必要がある - Gears OS ではメタレベルで通常の Code Gear で必要な Data Gear を Context から取り出す処理を行う stub Code Gear を用意している @@ -126,6 +126,8 @@ - Interface の定義には以下の内容を定義する - 操作(API)の引数群の型 - 操作(API)自体のCode Gear の型 +- **__code next(...)** は一種のクロージャであり、 引数で Code Gear を渡すことが出来る + - ... は可変長引数のような扱いで、Code Gear が複数の値をInput Data Gear とする可能性がある ``` c typedef struct Queue{ @@ -149,7 +151,7 @@ - 代入する Code Gear を入れ替えることで別の実装を表現する - 実装した Data Gear の生成は関数呼び出しで行われ、外から見るとInterface の型で扱われる -``` +``` c Queue* createSingleLinkedQueue(struct Context* context) { struct Queue* queue = new Queue(); // Allocate Queue interface struct SingleLinkedQueue* singleLinkedQueue = new SingleLinkedQueue(); // Allocate Queue implement @@ -164,29 +166,11 @@ } ``` -## Interface の実装例 -- SingleLinkedQueue の put 実装 -- 引数は Queue Interface の put 定義にあわせる -- 第1引数は 実装対象の Data Gear の型になる -- 第3引数の(...) は Output Data Gear を記述する - - ... は可変長引数のような扱いで、 継続先の Code Gear が複数の値をInput Data Gear とする可能性がある - -``` c -__code putSingleLinkedQueue(struct SingleLinkedQueue* queue, union Data* data, __code next(...)) { - Element* element = new Element(); - element->data = data; - element->next = NULL; - queue->last->next = element; - queue->last = element; - goto next(...); -} -``` - ## Interface を利用した Code Gear の呼び出し - Interface を利用した Code Gear への継続は `goto interface->method` で行われる - ここでの **interface** は Interfaceの型で包んだData Gear、 **method** は実装した Code Gear に対応する -``` +``` c __code code1() { Queue* queue = createSingleLinkedQueue(context); Node* node = new Node(); @@ -202,7 +186,7 @@ - この Data Gear は Context を初期化した際に特別に生成され、型は Interface と同じになる - 呼び出すCode Gear の引数情報に合わせて引数に格納し、 実装された Code Gear へ継続する -``` +``` c __code code1(struct Context *context) { Queue* queue = createSingleLinkedQueue(context); Node* node = &ALLOCATE(context, Node)->Node; @@ -219,7 +203,8 @@ - Interface を実装した Code Gear は Interface の定義から stub Code Gear の自動生成が可能である ``` c -__code putSingleLinkedQueue(struct Context *context,struct SingleLinkedQueue* queue, union Data* data, enum Code next) { +__code putSingleLinkedQueue(struct Context *context,struct SingleLinkedQueue* queue, + union Data* data, enum Code next) { Element* element = &ALLOCATE(context, Element)->Element; element->data = data; element->next = NULL; @@ -245,7 +230,7 @@ - Worker - SynchronizedQueue から Task を一つずつ取得し、実行する - Worker は CPU、 GPU の対応した数分生成する - - Worker 毎に POSIX Therad などのスレッドを生成し、 Code Gear を実行する + - Worker 毎に POSIX Therad などを生成し、それぞれのスレッドで Code Gear を実行する - SynchronizedQueue - マルチスレッド 環境でもデータの一貫性を保証する Queue - をInterface で実装した @@ -262,18 +247,12 @@ - 依存関係を解決した Task を各 Worker の Queue に送信する
    -
    - message -
    -
    + message +
      -
    1. Task を Input Data Gear として
    2. - TaskManager の spawn を呼び出す -
    3. Task内の idgCountをチェックする
    4. - idgCount は待っているInput Data Gear のカウンタである - そのため、カウンタが0の場合 Input Data Gear が揃っていることになる -
    5. 揃っている場合、 Worker の Queue に
    6. - Task を送信する +
    7. Task を Input Data Gear としてTaskManager の spawn を呼び出す
    8. +
    9. Task が待っている Data Gear のカウンタである idgCount をチェックする
    10. +
    11. idgCount が0の場合 Data Gear が 揃っているので Worker の Queue に Task を送信する
    @@ -284,18 +263,15 @@ - TaskManager から送信された Task を一つずつ取得して実行する
    -
    - message -
    -
    + message +
    1. Worker は Queue から Task を取得する
    2. -
    3. Worker の Context から
    4. - Task の Context へ入れ替える +
    5. Worker の Context からTask の Context へ入れ替える
    6. +
    7. Task に設定されている Code Gear を実行
    8. Task の Output Data Gear の書き出し
    9. -
    10. Task Context から
    11. - Worker の Context へ入れ替える +
    12. Task Context から Worker の Context へ入れ替える
    13. Worker は再び Queue から Task を取得する
    @@ -341,8 +317,13 @@ - この記述を直接書くと Meta Data Gear である Context を直接参照しているため、ノーマルレベルでの記述では好ましくない - Task の設定は煩雑な記述であるが、並列実行されることを除けば通常の CbC の goto 文と同等である - そこで Context を直接参照しない並列構文、 **par goto** 構文を新たに考案した + +## par goto 構文 +- par goto 構文を記述すると新しく Context を生成し、TaskManager を通して Worker に送信される - par goto 構文には引数として Input/Output Data Gear等を渡す - スクリプトによって Code Gear の Input/Output の数を解析する +- Task は **__exit** に継続することで終了する + - Gears OS は Output Data Gear 生成した時点で終了するため**__exit** に直接継続せずに Data Gear を書き出す処理に継続する ``` c __code code1(Integer *integer1, Integer * integer2, Integer *output) { @@ -413,11 +394,11 @@ ## Twice - Twice は与えられた整数配列を2倍にする例題である - 並列実行の依存関係がなく、並列度が高い課題である - -## Twice の結果 - 要素数 2^27 - CPU での実行時は 2^27 を 2^6 個に分割して Task を生成する - GPU での実行時は1次元の block 数を 2^15、 block 内の thread 数を 2^10 で展開 + +## Twice の結果 - 1 CPU と 32 CPU では 約27.1倍の速度向上が見られた - GPU 実行は kernel のみの実行時間は32 CPU に比べて約7.2倍の速度向上、通信時間を含めると 16 CPU より遅い - 通信時間がオーバーヘッドになっている @@ -466,11 +447,11 @@ ## BitonicSort - 並列処理向けのソートアルゴリズム - 決まった2点間の要素の入れ替えをステージ毎に並列に実行し、 Output Data Gear として書き出し、次のステージの Code Gear の Input Data Gear とする - -## BitonicSort の結果 - 要素数 2^24 - CPU での実行時は 2^24 を 2^6 個に分割して Task を生成する - GPU での実行時は1次元の block 数を 2^14、 block 内の thread 数を 2^10 で展開 + +## BitonicSort の結果 - 1 CPU と 32 CPU で約22.12倍の速度向上 - GPU は通信時間を含めると 8 CPU の約1.16倍、 kernel のみの実行では 32 CPU の約11.48倍になった - 現在の Gears OS の CUDA 実装では Output Data Gear を書き出す際に一度 GPU から CPU へ kernel の結果の書き出しを行っているため、差がでてしまった @@ -552,6 +533,35 @@ } ``` +## まとめ +- Gears OS の並列処理機構の実装を行った +- Interface を導入することで、見通しの良し Gears OS のプログラミングが可能となった +- par goto 構文を導入することで、ノーマルレベルで並列処理の記述が可能になった +- 2つの例題である程度の台数効果が出ることを確認した + +## 今後の課題 +- Gears OS の並列処理の信頼性の保証、チューニングを行う + +## 今後の課題 +- Gears OS では検証とモデル検査をメタレベルで実現することで信頼性を保証する + - 証明は CbC のプログラムを証明支援系の Agda に対応して行う。 並列処理の信頼性を保証するには SynchronizedQueue の証明を行う必要がある + - モデル検査は CbC で記述された モデル検査器である akasha を使用して行う。 モデル検査の方針としては Code Gear の並列実行を擬似並列で実行し、全ての組合せを列挙する方法で行う + +## 今後の課題 +- 現在の CUDA 実装では CPU、GPU 間のデータの通信コストがかかってしまうことが例題からわかった + - Meta Data Gear に Data Gear が CPU、 GPU のどこで所持されているのかを持たせ、 GPU の Data Gear が CPU で必要になったときに始めてデータの通信を行う + +## 今後の課題 +- OpenMP、 Go で Twice を実装し、 Gears OS の性能比較を行った +- その結果、 Gears OS が 1CPU での動作が遅いということがわかった。 + - par goto 文を使用する度に Context を生成するため、 ある程度の時間がかかってしまう + - モデル検査で par goto の Code Gear のフローを解析し、処理がかる場合は Context を生成せずに関数呼出しを行う等の最適化が必要 + +
    + message +
    + +