view slide/index.html @ 74:ec6ddf37a60b

fix slide
author Masataka Kohagura <e085726@ie.u-ryukyu.ac.jp>
date Wed, 26 Feb 2014 04:08:26 +0900
parents d5b9addca752
children e13727d01f7a
line wrap: on
line source

<!DOCTYPE html>

<html>
  <head>
    <title>Presentation</title>

    <meta charset='utf-8'>
    <script
       src='./slides.js'></script>
  </head>

  <style>
    /* Your individual styles here, or just use inline styles if that’s
    what you want. */

  </style>

  <body style='display: none'>
    <section class='slides layout-regular template-default'>

      <!-- 
           Your slides (<article>s) go here. Delete or comment out the
           slides below.
        -->
      <article >
        <h1>Cerium による並列処理向け I/O の設計と実装</h1>
        <h3 class="title">Masataka Kohagura 12th, February</h3>
        <div align="right">担当教官 : 河野 真治</div>
      </article>

        <article>
        <h3>研究背景と目的</h3>
        <p>
        近年のCPUのほとんどはマルチコアであり、それらの性能を引き出すためには並列プログラミングが必須となっている。
        そこで当研究室では、並列プログラミング用フレームワーク、Cerium 及び Cerium Task Manager の開発を行い、提供することによって並列プログラミングを容易にしている。
        </p>
        <p>
        先行研究では Task の並列化によって、プログラム全体の処理速度は向上している。しかし、ファイル読み込み等の I/O処理 と Task が並列に動作するようにはされていない。
        </p>
        <p>
        本研究では I/O処理 と Task が並列に動作するような設計、実装によってプログラム全体の並列度、及び処理速度を上げていく。
        </p>
      </article>


        <article>
        <h3>Cerium Task Manager について</h3>
        <ul>
        <li>
        当研究室で開発している並列プログラミングフレームワーク。
        </li>
        <li>
        PS3 に搭載されている Cell 向けに開発を行っていた。近年では、Mac OS X、Linux でも使用ができるように改良された。
        </li>
        </ul>
      </article>

      <article>
        <h3>並列処理向け I/O の 設計と実装</h3>
          <br>
          <ul>
            <li>I/O を含む Task の説明</li>
            <li>mmap の説明</li>
            <li>Blocked Read の設計と実装</li>
            <li>IO専用 therad の追加</li>
            <li>ベンチマーク</li>
          </ul>
      </article>

      <article>
        <h3>I/O を含む Task の説明</h3>
          <br>
          <img src='images/includeIOTask.png' style="height:250px" align="middle">
          <ol>
            <li>テキストファイルの読み込み後、ファイルをある一定の大きさに分割する</li>
            <li>分割したテキストファイルに対して、それぞれ計算を行う</li>
            <li>計算した結果を集計する</li>
          </ol>
      </article>

      <article>
        <h3>mmap の特徴</h3>
        <table  border="0" cellpadding="0" cellspacing="0">
          <tbody>
            <tr>
              <td><img src='images/mmap.png' style="height:350px" align="middle"></td>
              <td>
                <ul>
                <font size = 5>
                    <li>
                    mmap は、C 及び C++ で使用でき、ファイルを読み込む API である。
                    </li>
                  <li>
                  code がシンプル <br>(メモリを自分自身で malloc せず、read を書いて読み込まなくていいため)
                  </li>
                  </font>
                </ul>
              </td>
            </tr>
          </tbody>
        </table>

        <ul>
        </ul>
      </article>

        <article>
        <h3>mmapでの実装の問題点</h3>
        <ul>
        <li>
        mmap でファイルを読み込むと、ファイルはメモリ上に即座に展開されるわけではない。
        </li>
        <li>
        ファイルがメモリに展開されるタイミングは、そのファイルに対して文字列検索を行うときである。<br><br>
        →つまり、文字列検索が行われるときに初めてメモリにファイルが格納されるので、ファイル読み込みと文字列検索が分離できない。
        </li>
        </ul>
      </article>


      <article>
        <h3>Blocked Read の設計</h3>
          <br>
          <img src='images/divide_read.png' style="height:250px" align="middle" >
          <br>

        <ul>
          <li>
          メモリへの呼び出しを自分で書ける(制御できる)
          </li>
        </ul>
        以後、ファイルに対して文字列検索を行う処理を Task と定義する。
      </article>

      <article class='smaller'>
        <h3>Blocked Read の実装</h3>
          <br>
          <img src='images/blockread.png' style="height:250px"align="middle">
          <br>

        <ul>
          <li>
          Task を 1 つずつ生成するのではなく、ブロック単位で生成する。<br>
          この図では、1 Block 当たり n 個の Task を生成する。<br>
          (1つずつ生成すると、生成された Task でメモリを圧迫するため)
          </li>
          <li>
          Task 1つ当たりの読み込む領域を L とする。<br>
          Blocked Read Task 1つ当たり、メモリに格納する大きさは L × n となる。
          </li>
          <li>
          Blocked Read Task が読み込み終わるまで、Task Block に wait を掛ける。<br>
          (Read Task がファイルをメモリに格納する前に走ると、まだ格納していない領域を読みこんでしまう。)
          </li>
        </ul>
      </article>

      <article class = 'smaller'>
        <h3>I/O 専用の therad を追加 (1/2)</h3>
          <br>
          <img src='images/SPE_ANYblockread.png' style="height:350px"align="middle">
        <ul>
          <li>
          Task 単位で使用するデバイスをセットすることができる。
          </li>
          <li>
          SPE_ANY でセットすると、Cerium Task Manager 側で自動的に CPU を割り振る。
          </li>
          <li>
          自動的に割り振るので、Blocked Read に 他のTask が割り込むおそれがある。
          </li>
        </ul>
      </article>


      <article class='smaller'>
        <h3>I/O 専用の therad を追加 (2/2)</h3>
          <br>
          <img src='images/IO_0blockread.png' style="height:350px">
          <ul>
            <li>IO_0 という I/O 専用の Thread を追加した。</li>
            <li>Blocked Read Task が最優先されるので、他の Task に割り込まれなくなる<br>
                これにより、Blocked Read Task が連続で動作する。
            </li>
          </ul>
      </article>

      <article>
        <h3>ベンチマーク(1/2)</h3>
          <br>
              <h3 class="yellow">実験環境</h3>
              <ul>
              <li> Mac OS X 10.9.1</li>
              <li> 2*2.66 GHz 6-Core Intel Xeon</li>
              <li> Memory 16GB 1333MHz DDR3</li>
              <li> HHD 1TB</li>
              <li> file size : 約 10 GB</li>
              <li> ファイルに対して Boyer-Moore String Seaech で文字列検索をかける </li>
              <li> ファイルの読み込みから結果までを測定</li>
              </ul>
      </article>

      <article class = 'smaller'>
        <h3>ベンチマーク(2/2)</h3>
        <ul>
            <li>
            ファイルがキャッシュに残っていない状態での測定
            </li>
            <li>
            one task size 128KByte
            </li>
            <li>
            Task Blocks 48
            </li>
            <li>
            CPU num 12
            </li>
        </ul>
        <br>
          <h3 class="yellow">結果</h3>
        <table  border="0" cellpadding="0" cellspacing="0">
          <tbody>
            <tr>
              <td>read mode</td>
              <td>ave time(s)</td>
            </tr>
            <tr>
              <td>mmap</td>
              <td>154.6</td>
            </tr>
            <tr>
              <td>一括Read</td>
              <td>114.9</td>
            </tr>
            <tr>
              <td>Blocked Read & SPE_ANY</td>
              <td>106.0</td>
            </tr>
            <tr>
              <td>Blocked Read & IO_0</td>
              <td>99.2</td>
            </tr>
            <tr>
              <td>[参考] mmap (CPU num:2)</td>
              <td>106.2</td>
            </tr>
          </tbody>
        </table>

      </article>


      <article>
        <h3>考察</h3>
          <br>
            <ul>
            <li>
            実験結果から、mmap より、Blocked Read & IO_0 の実行速度が36%改善された。<br>
            </li>
            <li>
            mmap では 1つ1つの Task がファイルの読み込みを行うが、Blocked Read だと複数 Task 分のファイルを読み込んでいるので、メモリへの呼び出し回数が少ない Blocked Read のほうが速くなったと考えられる。
            </li>
            <li>
            I/Oを含む並列処理を mmap で実装すると遅くなるので、このような例題の場合は Blocked Read で読み込む必要がある。
            </li>
            </ul>

      </article>

      <article>
        <h3>まとめ</h3>
          <br>
            <ul>
            <li>
            I/O を含む Task を実装するときに mmap では不向き
            </li>
            <li>
            I/O を含む Task では Blocked Read で読み込みを制御したほうが効果的
            </li>
            </ul>
      </article>

      <article>
        <h3>Cerium Task の生成の例(1)</h3>
        <p>(例題) multiply : 2つの数を掛け算するプログラム</p>
          <h3 class="yellow">main.cc の記述</h3>
        <pre>
float* A, B, C;
// Task の宣言
HTaskPtr multiply = manager->create_task(MULTIPLY_TASK);
// Task を実行する デバイスの設定
multiply->set_cpu(SPE_ANY);
// Task に入力データのアドレスを追加
multiply->set_inData(0, (memaddr)A, sizeof(float)*length);
multiply->set_inData(1, (memaddr)B, sizeof(float)*length);
// Task に出力データのアドレスを追加
multiply->set_outData(0, (memaddr)C, sizeof(float)*length);
// Task へ値を1つだけ渡す
multiply->set_param(0,length);
// Task を TaskList に set する
multiply->spawn(); </pre>
      </article>

      <article>
        <h3> Cerium Task の生成(2)</h3>
          <br>
          <h3 class="yellow">Task の記述</h3>
        <pre>
static int
multiply(SchedTask *s,void *rbuf, void *wbuf)
{
    float *A,*B,*C
    // 登録した inData を取得
    A = (float*)s->get_input(rbuf,0);
    B = (float*)s->get_input(rbuf,1);
    // 登録した outData を取得
    C = (float*)s->get_output(wbuf,0);
    // 登録した param を取得
    long  length=(long)s->get_param(0);
    for (int i=0;i &lt; length;i++) {
        C[i] = A[i] * B[i];
    }
    return 0;
} </pre>
      </article>

      <article>
        <h3>mmap での I/O の実装</h3>
          <br>
          <h3 class="yellow">mmap の記述</h3>
        <pre>
mmap(SchedTask *s, void *in, void *out)
{
    // FileReadPtr : File情報などを格納している構造体
    FileReadPtr fr = (FileReadPtr)in;
    int map = MAP_PRIVATE;

    fr->read_text =
        (char*)mmap(NULL,fr->filesize,PROT_READ,map,fr->fd,(off_t)0);
}
</pre>
        <ul>
            <li>
            PROT_READ : 読み込み可
            </li>
            <li>
            MAP_PRIVATE : 読み込んだ領域に対して書き込みが起こると複製し、複製した領域に対して書き込みを行う
            </li>
        </ul>
      </article>

      <article class='smaller'>
        <h3>Block Read の実装(1/2)</h3>
          <br>
          <h3 class="yellow">Block Read の実装</h3>
        <pre>
HTaskPtr t_read = manager->create_task(READ_TASK);
t_read->set_cpu(read_spe_cpu);
// 読み出すファイルの格納場所を設定
t_read->set_outData(0,
                    w->file_mmap + w->task_spawned * w->division_size,
                    w->task_blocks * w->division_size);
// ファイルディスクリプタの受け渡し
t_read->set_param(0,w->fd);
// ファイル読み込みの始点
t_read->set_param(1,w->task_spawned*w->division_size);

// run_tasks(manager,w, w->task_blocks, t_read, t_next, w->division_size + w->extra_len);
// ここで、ファイルに対して何らかの計算を掛けるような Task を設定する
run_tasks(manager,w, w->task_blocks,・・・ );

// ファイル読み込みの終点
t_read->set_param(2,w->task_spawned*w->division_size + w->extra_len);

t_read->spawn();

</pre>
      </article>

      <article>
        <h3>Block Read の実装(2/2)</h3>
          <br>
          <h3 class="yellow"> Block Read の記述</h3>
        <pre>
static int
read_task(SchedTask *s, void *rbuf, void *wbuf)
{
    long fd = (long)s->get_param(0);
    long start_read_position = (long)s->get_param(1);
    long end_read_position = (long)s->get_param(2);
    char *read_text = (char*)s->get_output(wbuf,0);
    long read_size = end_read_position - start_read_position;

    pread(fd, read_text, read_size , start_read_position);
    return 0;
}
</pre>
      </article>


  </body>
</html>