Mercurial > hg > Papers > 2014 > masakoha-thesis > final
view slide/index.html @ 35:d5b9addca752
add OUTLINE chapter2
author | Masataka Kohagura <e085726@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 14 Feb 2014 03:17:44 +0900 |
parents | 717d9793d33e |
children | ec6ddf37a60b |
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> <li> マルチコア CPU だけでなく、GPGPU での動作もサポート。 </li> </ul> </article> <article> <h3>用語の定義</h3> <ul> <li> Blocked Read Task<br> ファイルを実メモリに読み込む処理 </li> <li> Task<br> 分割されたファイルに対して何らかの計算を行う処理<br> </li> </article> <!-- <article> <h3>Cerium Task Manager の流れ</h3> <table border="0" cellpadding="0" cellspacing="0"> <tbody> <tr> <td><img src='images/cerium.png' style="height:350px"></td> <td> <ol> <font size=5> <li>Taskを生成後、Task Managerにて Task の管理、依存関係のチェック</li> <li>TaskList に生成された Task を set </li> <li>Task を各 Scheduler に転送</li> <li>並列実行</li> </font> </ol> </td> </tr> </tbody> </table> </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>file を実メモリに格納後、file をある一定の大きさに分割する</li> <li>分割した file に対して、それぞれ計算を行う</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であり、ファイルを仮想メモリに mapping する。 </li> <li> code がシンプル <br>(実メモリを自分自身で malloc せず、read を書いて読み込まなくていいため) </li> <li> 実メモリより大きなファイルは開けない </li> </font> </ul> </td> </tr> </tbody> </table> <ul> </ul> </article> <article> <h3>mmapでの実装の問題点</h3> <ul> <li> mmap で file を読み込むと、file は実メモリ上にて即座には展開されない。 </li> <li> 実メモリへの呼び出しがOS依存。 </li> <li> file が実メモリに展開されるタイミングは、その file に対して何らかの計算を行うときである。<br><br> →つまり、Task が走るときに初めて実メモリに file を格納するので、I/O と Task が分離できない。 </li> </ul> </article> <article> <h3>Blocked Read の設計</h3> <br> <img src='images/divide_read.png' style="height:250px" align="middle" > <br> <ul> <li> 明示的な read </li> <li> 実メモリへの呼び出しを自分で書ける(制御できる) </li> <li> 実メモリより大きなファイルを扱える </li> </ul> </article> <!-- <article> <h3>divide read の実装(1)</h3> <br> <h3 class="yellow">Read Task の ブロック化</h3> <pre> program_run(TaskManager *manager, char *filename) { FileReadPtr fr = (FileReadPtr)manager->allocate(sizeof(FileRead)); fr->self = fr; fr->fd = fd; ・・・ read = manager->create_task(RUN_READ_BLOCKS, (memaddr)&fr->self, sizeof(memaddr),read_text,fr->filesize); read->spawn(); } </pre> </article> <article> <h3>divide read の実装(2)</h3> <br> <ul> <li> divide read Task の実行の際に、ブロック単位で Task の生成、実行を行う。 </li> <li> 1つずつ生成すると Task の数だけ memory address が取られるために肥大化してしまう。 </li> <li> しかしブロック単位で生成すると、同じ変数を使用しているので memory の節約になる。 </li> </li> </ul> </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 単位で CPU Type を set することができる。 </li> <li> SPE_ANY で set をすると、Cerium Task Manager 側で自動的に CPU を割り振ってくれる。 </li> <li> 自動的に割り振るので、Blocked Read に割り込むおそれがある。 </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 という CPU Type を実装した。</li> <li>他の CPU Type より priority を高く設定している。</li> <li>Blocked Read Task が他の Task に割り込まれないので、<br> 連続で動作する。 </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> "doing" という文字列が file 内にいくつあるか計算<br> ("doing" は 25,961,792 個存在する) </li> </ul> </article> <article class = 'smaller'> <h3>ベンチマーク(2/2)</h3> <ul> <li> file がメモリに残っていない状態での測定 </li> <li> one task size 128KByte </li> <li> Task Blocks 48 </li> </ul> <br> <h3 class="yellow">結果</h3> <table border="0" cellpadding="0" cellspacing="0"> <tbody> <tr> <td>read mode</td> <td>cpu num</td> <td>min time(s)</td> <td>MAX time(s)</td> <td>ave time(s)</td> </tr> <tr> <td>mmap</td> <td>4</td> <td>135.2</td> <td>148.9</td> <td>142.3</td> </tr> <tr> <td>BRead</td> <td>4</td> <td>94.5</td> <td>109.2</td> <td>98.8</td> </tr> <tr> <td>mmap</td> <td>12</td> <td>147.0</td> <td>181.8</td> <td>154.6</td> </tr> <tr> <td>BRead</td> <td>12</td> <td>91.6</td> <td>117.5</td> <td>99.2</td> </tr> </tbody> </table> </article> <article> <h3>まとめ</h3> <br> <ul> <li> mmap より、Blocked Readのほうが約50秒高速化した<br> mmap では 1つ1つの Task が実メモリへの呼び出しを行っているが、Blocked Read だと複数 Task 分の実メモリ呼び出しを行っている。実メモリへの呼び出し回数が少なくなったため速くなっていると考えられる。(要検証) </li> <li> I/O と Task の分離が成功して並列に動作するようになった </li> </ul> </article> <article> <h3>Blocked Read の有効性</h3> <br> <ul> <li> mmap で記述するよりも速度的に速くなる </li> <li> 読み込みのOS 依存度が減少する。 </li> </ul> </article> <article> <h3>研究計画</h3> <br> <ul> <li> さらなる 並列処理向け I/O の動作を改善 </li> <li> I/O を利用した、マルチコアソフトウェアシンセサイザーを設計と実装 </li> </ul> </article> <article> </article> <article> <h3>マルチコアソフトウェアシンセサイザーの設計</h3> <br> <ul> <li> 作曲をする際にはマシンパワーが必要となることが多い。 </li> <li> ソフトウェアシンセサイザー(以下、シンセサイザー)を使用する際にマシンパワーが必要となる。 </li> <li> シンセサイザーは1つだけで立ち上げる物ではなく、複数立ち上げる物なので、1つ1つの負荷を抑えることがキーポイントとなる。 </li> <li> シンセサイザーは様々なフィルターをかけることで音を作っていくのだが、フィルターを重ねても動作軽量なプログラムを作る。 </li> </ul> </article> <article> <h3>仮想メモリと実メモリ</h3> <br> <ul> <li> 実メモリ<br> 物理メモリとも呼ばれている。コンピュータに実際に搭載されているメインメモリ。 </li> <li> 仮想メモリ<br> HDD などの補助記憶装置上に仮想的なメモリ領域を確保する。仮想メモリ上と仮想メモリ上の領域の対応付けを行う。 </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 < 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>