Mercurial > hg > Papers > 2015 > yuhi-master
view slide/blank.html @ 79:7990a2abbf05 default tip
add file
author | Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 02 Mar 2015 11:21:40 +0900 |
parents | 9640b2a212ec |
children |
line wrap: on
line source
<!DOCTYPE html> <html> <head> <meta charset='utf-8'> <title>Seminar</title> <!-- Notes on CSS media types used: 1) projection -> slideshow mode (display one slide at-a-time; hide all others) 2) screen -> outline mode (display all slides-at-once on screen) 3) print -> print (and print preview) Note: toggle between projection/screen (that is, slideshow/outline) mode using t-key Questions, comments? - send them along to the mailinglist/forum online @ http://groups.google.com/group/webslideshow --> <!-- style sheet links --> <link rel="stylesheet/less" href="themes/blank/projection.css.less" media="screen,projection"> <link rel="stylesheet/less" href="themes/blank/screen.css.less" media="screen"> <link rel="stylesheet/less" href="themes/blank/print.css.less" media="print"> <link rel="stylesheet/less" href="blank.css.less" media="screen,projection"> <!-- Notes about less css support - all less stylesheets (*.css.less) need to get listed/loaded first (before the less.js script) - find more info about less.js online @ http://lesscss.org ***** NOTE: less.js browser script currently won’t work if you’re using Google Chrome and the path to your page starts with "file:///" due to a known Chrome issue. (In the developer/js console you will see: XMLHttpRequest cannot load file:///../s6/shared/projection.css.less. Cross origin requests are only supported for HTTP.) --> <!-- add js libs (less, jquery) --> <script src="js/less-1.1.4.min.js"></script> <script src="js/jquery-1.7.min.js"></script> <!-- S6 JS --> <script src="js/jquery.slideshow.js"></script> <script src="js/jquery.slideshow.counter.js"></script> <script src="js/jquery.slideshow.controls.js"></script> <script src="js/jquery.slideshow.footer.js"></script> <script src="js/jquery.slideshow.autoplay.js"></script> <script> $(document).ready( function() { Slideshow.init(); // Example 2: Start Off in Outline Mode // Slideshow.init( { mode: 'outline' } ); // Example 3: Use Custom Transition // Slideshow.transition = transitionScrollUp; // Slideshow.init(); // Example 4: Start Off in Autoplay Mode with Custom Transition // Slideshow.transition = transitionScrollUp; // Slideshow.init( { mode: 'autoplay' } ); } ); </script> <!-- Better Browser Banner for Microsoft Internet Explorer (IE) --> <!--[if IE]> <script src="js/jquery.microsoft.js"></script> <![endif]--> </head> <body> <div class="layout"> <div id="header"></div> <div id="footer"> <div align="right"> <img src="images/concurrency.png" width="200"> </div> </div> </div> <div class="presentation"> <!-- add slides here; example --> <div class='slide cover'> <table width="90%" height="90%" border="0" align="center"> <tr> <td><div align="center"> <h1><font color="#808db5">マルチプラットフォーム対応<br>並列プログラミングフレームワーク</font></h1> </div></td> </tr> <tr> <td><div align="left"> Yuhi TOMARI <script> var date = new Date(); var year = date.getFullYear(); var month = date.getMonth(); var day = date.getDate(); var monthList = new Array("January","February","March","April","May","June", "July","August","September","October","November","December"); document.write(monthList[month]+" "+day+", "+year); </script> <hr style="color:#ffcc00;background-color:#ffcc00;text-align:left;border:none;width:300%;height:0.2em;"> </div></td> </tr> </table> </div> <div class='slide'> <h2>マルチプラットフォームなフレームワークにおける並列プログラミング 1/2</h2> <p> 消費電力や発熱、クロックの限界といった問題から CPU の性能を上げることによる処理性能の向上は難しい。 マルチコア CPU や GPU を含んだヘテロジニアス構成が主流になっている。 クロックの性能を上げるのではなく、コア数を増やす事でパフォーマンスを向上させている。 </p> <p> マルチコア CPU や GPU といった<font color="red">マルチプラットフォーム</font>なアーキテクチャ上で リソースを有効活用するには、それぞれのプラットフォームに最適な形でプログラムを並列に動作させる必要がある。 </p> <p>しかしこれらのチューニングは複雑で、コーディング時に毎回行うと煩雑さや拡張性の問題がある。</p> </div> <div class='slide'> <h2>マルチプラットフォームなフレームワークにおける並列プログラミング 2/2</h2> <p> そういった問題を解決するため、本研究では並列プログラミングフレームワーク、 Cerium の開発を行った。 異なるプラットフォーム上で最適なチューニングを行うため、以下の実装を行った。 </p> <ul> <li>パイプライニングによる Task の並列実行</li> <li>OpenCL、CUDA を用いた GPGPU 対応</li> <li>データ並列実行のサポート</li> <li>並列処理むけのI/Oの実装</li> </ul> <p> Sort、WordCount、FFT といった例題を元に測定・評価を行った。 </p> </div> <div class='slide'> <h2>並列プログラミングフレームワーク Cerium</h2> <p> Cerium は Linux、MacOSX 上で動作する汎用計算用の並列プログラミングフレームワークである。 </p> <div align="center"> <img src="./images/cerium_image.png" width="700"> </div> <p> Cerium はマルチコア CPU と GPU における Scheduling をサポートし、 より並列度の高いプログラミングを可能とする。 </p> </div> <div class='slide'> <h2>Cerium における Task の生成</h2> <p> Cerium TaskManager では処理の単位を Task としてプログラムを記述していく。 関数やサブルーチンを Task として扱い、Task に各種パラメタを設定した後に並列実行される。 Input データの各要素同士を乗算し、 Output に格納する Multiply という例題がある。 Multiply の例題を元に Cerium で Task が生成される様子を以下に示す。 </p> <pre class="code"> void multiply_init(TaskManager *manager, float *i_data1, float *i_data2, float *o_data) { // create task HTask* multiply = manager->create_task(MULTIPLY_TASK); // set indata multiply->set_inData(0, i_data1, sizeof(float) * length); multiply->set_inData(1, i_data2, sizeof(float) * length); // set outdata multiply->set_outData(0, o_data, sizeof(float) * length); // set parameter multiply−>set_param(0,(long)length); // set device multiply->set_cpu(SPE_ANY); // spawn task multiply−>spawn(); } </pre> </div> <div class='slide'> <h2>Cerium における Task の記述</h2> <p>Device 側で実行される Task の記述を示す。</p> <pre class="code"> static int run(SchedTask ∗s) { float ∗i_data1 = (float∗)s−>get_input(0); // get input float ∗i_data2 = (float∗)s−>get_input(1); // get output float ∗o_data = (float∗)s−>get_output(0); // get parameter long length = (long)s−>get_param(0); // calculate for (int i=0; i<length; i++) { o_data[i] = i_data1[i] ∗ i_data2[i]; } return 0; } </pre> <p>Host 側では Task を生成する際に様々なパラメタを設定しており、 Task にはそれを取得する API が用意されている。</p> <table border="0" > <tr bgcolor="palegreen"> <th align="center">API</th><th align="center">content</th> </tr> <tr bgcolor="dbffa3"> <th align="left" >get_input</th><th align="left">入力データのアドレスを取得</th> </tr> <tr bgcolor="palegreen"> <th align="left">get_output</th><th align="left">出力先データのアドレスを取得</th> </tr> <tr bgcolor="dbffa3"> <th align="left">get_param</th><th align="left">パラメータを取得</th> </tr> </table> </div> <div class='slide'> <h2>Task の依存関係の記述</h2> <p> 並列処理を行う場合、Task を大量に生成する場合がある。 そういった場合において一括で Task を生成/実行してしまうと並列度が落ちてしまう。 これは生成しただけで Task そのものがメモリを圧迫してしまっていることが原因となる。 </p> <p> 一般的な並列処理において、Task は一定数ずつ徐々に生成/実行する必要がある。 ということは Task 間で wait が入るため、Task の Block 間で依存関係を設定する必要がある。 依存関係について Cerium の Bitonic Sort を例題に考える。 </p> </div> <div class='slide'> <h2>Bitonic Sort の例題</h2> <p>Bitonic Sort は配列の分割を行い、分割した部分に対して Sort を行う。 分割後の Sort には QuickSort を使用している。Bitonic Sort は2つの Sort を行う。 </p> <ul> <li>使用する CPU 数を元に分割数を算出し、分割した箇所に対して Sort する(fsort) <li>Block の中間から次の Block の中間までを Sort する(bsort) </ul> <p>この2つの Sort を分割数分繰り返している</p> </div> <div class='slide'> <h2>Bitonic Sort の例題</h2> <div align="center"> <img src="./images/fsort_bsort.png" width="850"> </div> </div> <div class='slide'> <h2>Task 間の依存関係</h2> <p>Bitonic Sort を行う際、依存関係として bsort は fsort の結果に対して sort を行い、 fsort は前の Stage の bsort に対して Sort を行う必要がある </p> <p>よって、BitonicSort のような大量に Task を生成する例題を並列実行する場合、 「例題の性質としての依存関係」と「Task を徐々に生成するための依存関係」 の二種類の依存関係を記述する必要がある。</p> </div> <div class='slide'> <h2>依存関係の記述</h2> <p>例題独自の依存関係</p> <pre class="code" align="left">static int sort_start(SchedTask *manager, void *d, void *e) { Sort *s = (Sort*)manager->get_param(0); long half_num = s->split_num-1; for (int i = 0; i < s->split_num-1; i++) { s->fsort[i] = manager->create_task(QUICK_SORT,(memaddr)&s->data[i*block_num], sizeof(Data)*block_num, (memaddr)&s->data[i*block_num], sizeof(Data)*block_num); s->fsort[i]->wait_for(s->bsort[i-1]); } ~省略~ </pre> </div> <div class='slide'> <h2>依存関係の記述</h2> <p>Task を徐々に生成するための依存関係</p> <pre class="code" align="left"> // recursive Task HTaskPtr restart = manager->create_task(SortSimple,0,0,0,0); restart->set_param(0,(memaddr)s); restart->wait_for(s->fsort[0]); for (int i = 0; i < s->split_num; i++) { s->fsort[i]->spawn(); } restart->spawn(); return 0; } </pre> </div> <div class='slide'> <h2>TaskManager の構成</h2> <div align="center"> <img src='images/createtask.png' width="700"> </div> <ul> <li>TaskManagerと各Threadsの間には Syncronized な Mail Queueがある。 <li>依存関係の解決された Task は TaskManager から Mail Queue に送られる。 <li>Task に設定された CPUType に対応した Threads が Mail Queue から Task を取得し、並列実行していく。 </ul> </div> <div class='slide'> <h2>マルチコア CPU 上での並列実行</h2> <div align="center"> <img src="images/pipeline.png" width="600"> </div> <p> Cerium は Cell 上で動作するフレームワークであったが MacOSX、Linux 上での並列実行に対応させた。 </p> <p> マルチコア CPU 上での並列実行は、Synchronized Queue とパイプラインによって実現されている。 TaskManager で依存関係を解決された Task は Scheduler に送信され、 Scheduler が持っているパイプラインの機構に沿って並列に実行する。 </p> </div> <div class='slide'> <h2>マルチコア CPU におけるパイプラインの実装</h2> <table> <tr> <th> <pre class="code" align="left">void Scheduler::run(SchedTaskBase* task1) { SchedTaskBase* task2 = new SchedNop(); SchedTaskBase* task3 = new SchedNop(); // main loop do { task1->read(); task2->exec(); task3->write(); delete task3; task3 = task2; task2 = task1; task1 = task1->next(this, 0); } while (task1); delete task3; delete task2; }</pre> </th> <th align="left"> <p> Cerium の Task は SchedTask と呼ばれるデータ構造で表現されている。 SchedTask は read/exec/write のメソッドを持っており、 パイプラインの各ステージで段階的に実行される。 </p> <p> 引数として TaskList を受け取り、List 内の Task をパイプライン実行する。 task3 が write を担当しており、write が終わった Task は終了となる。 </p> <p> 終了した task は delete して良い。 task3=task2、task2=task1 と SchedTask をずらして行き、TaskList から 次の Task を読み込む。 </p> </th> </tr> </table> </div> <div class='slide'> <h2>マルチコア CPU におけるデータ並列</h2> <p> Cerium はタスク並列による実行のみを行っていた。 並列化を行う問題によってはデータ並列を行った方が良い場合がある。 </p> <p> タスク並列は1つのデータに対して異なる処理方法を適用し、それぞれ独立して実行させるものである。 </p> <p> データ並列は多くのデータを1つのタスクに与え、データごとに独立した処理を行わせる手法である。 </p> <p>処理対象となるデータが充分な数のサブセットへ分割可能な場合、データ並列が有効となる。</p> <p>Cerium をデータ並列に対応させた。</p> </div> <div class='slide'> <h2>iterate API</h2> <p> データ並列による実行を行う場合、一つの記述から複数のTaskを生成する必要がある。 データ並列用の Task を生成する「iterate」というAPIを実装した。 </p> <table> <tr> <td> <img src="images/iterate.png" height="450"></img> </td> <td> <ul> <li>1つの記述から複数のTaskを生成する</li> <li>生成した複数のTaskにIDとInput/Output Dataを割り当てる</li> </ul> この例だと、Taskの持つidとTaskに割り当てられるデータは 1対1で対応している。id=割り当てられたdataのindexとなっている。<br><br> 並列プログラミングだと、並列化部分が全て同一の Task であるという場合は少なくない。 iterate API ならループで回すような処理をする必要が無く、容易な Syntax で記述できる。 </td> </tr></table> </div> <div class='slide'> <h2>マルチコア CPU によるデータ並列実行</h2> <p> マルチコア CPU においてデータ並列実行する場合、以下のように記述する。 例題として 2つの input のデータの積を output データに格納して返す例題、multiply を用いた。 </p> <pre class="code"> static int run(SchedTask *s, void *rbuf, void *wbuf) { float *indata1, *indata2, *outdata; indata1 = (float*)s->get_input(rbuf, 0); indata2 = (float*)s->get_input(rbuf, 0); outdata = (float*)s->get_output(wbuf, 0); long id = (long)s->get_param(0); outdata[id] = indata1[id] * indata2[id]; return 0; } </pre> <p>get_param によって自分の担当する index を取得し、担当範囲のみを計算する。</p> <p>データ並列実行する場合、各Task に Input/Output を設定するのではなく、 全ての Task でデータを共有する。共有したデータの自分の担当する箇所にのみ計算を行う。 そのため少ないコピーにおさえることができる。 </p> </div> <div class='slide'> <h2>DMA 転送</h2> <p>Cerium は DMA 転送をサポートしている。 DMA とは CPU を介さずに周辺装置とメモリ間でデータ転送を行う転送方式である。 </p> <p> DMA は prefetch と呼ばれる転送先読みの機能がある。 DMA の転送効率を向上させるために送信データを予め取り込んでおく機能である。 prefetch による転送機能を追加した。 </p> </div> <div class='slide'> <h2>GPU 上での並列実行</h2> <p> GPU 上での並列実行をサポートするフレームワークとして、OpenCL と CUDA が挙げられる。 これらのフレームワークを用いて Cerium に GPU 上で 並列実行する機能を加えた。 </p> <p> TaskManager から受け取った Task やデータをOpenCL、CUDA の API を介して GPU に転送する機構、 GpuScheduler と CudaScheduler を実装した。 </p> <div align="center"> <img src="./images/gpu_image.png" width="600"> </div> </div> <div class='slide'> <h2>フレームワークを用いた GPU の制御</h2> <p> GpuScheduler、CudaScheduler ではそれぞれのフレームワークを用いて GPU の制御を行っている。 行われていることは以下の3つに分けられる。 </p> <ul> <li>Host から Device へのデータ転送 <li>kernel の実行 <li>Device から Host へのデータ転送 </ul> <p> CommandQueue と呼ばれる機構を用いてこういった GPU を制御するための処理を行っていく。 CommandQueue は GPU に命令を送るためのしくみで、制御は全てこの Queue を介して行われる。 </p> <p>これらはRead, Exec、Write に対応する。 GPGPU 用の Scheduler でもパイプラインを構成する。</p> </div> <div class='slide'> <h2>GPGPU におけるパイプラインの実装</h2> <p> GpuScheduler では SchedTask を用いてない。 メインループでは2つの CommandQueue を保持し、GPU の制御命令を二段のパイプラインで実行していく。 TaskList から Task を取り出し、Task から実行する kernel やパラメタを生成し、 各種フレームワークの API を通して GPU のメモリに転送される。 </p> <p> 全ての Task が終了すると SynchronizedQueue を通してTaskManager に終了を通知する。 </p> <p> Scheduler の内部で Platform や DeviceID の取得、 kernel の build や load といった API を使用するための初期化も行っており、 並列化したい処理のみに集中できる。 </p> </div> <div class='slide'> <h2>GPGPU におけるデータ並列</h2> <p> マルチコア CPU と同様に、GPGPU に関してもデータ並列実行をサポートした。 </p> <p> GPU 上でデータ並列実行する際も iterate API によりデータ並列用の Task を生成できる。 生成部分の記述はマルチコア CPU と同じ形式で記述できる。 また、Task 自体の記述もほぼ同じ形式となる。以下に Task の例を示す。 </p> <table> <tr align="left"> <th> <pre class="code"> __kernel void // OpenCL multiply(__global const long *params, __global const float *input1, __global const float *input2, __global const float *output) { long id = get_global_id(0); output[id] = input1[id] * input2[id]; } </pre> </th> <th> <pre class="code"> __global__ void // CUDA multiply(__global const long *params, __global const float *input1, __global const float *input2, __global const float *output) { int id = blockIdx.x * blockDim.x + threadIdx.x; output[id] = input1[id] * input2[id]; } </pre> </th> </tr> </table> </div> <div class='slide'> <h2>並列処理向け I/O</h2> <p> ファイルの読み込みなどの I/O を含むプログラムは、 読み込み時間が Task と比較してオーバーヘッドになることが多い。 プログラムの並列化を行ったとしても I/O がボトルネックになってしまうと処理は高速にならない。 </p> <p>並列計算と同時に動作する、並列 I/O の実装を行った。</p> </div> <div class='slide'> <h2>Cerium の I/O(mmap による読み込み)</h2> <p> Cerium ではファイルの読み込みを mmap で行っていた。</p> <ul> <li>mmap はまず仮想メモリにファイルをマッピングする。 <li>マッピングしたメモリ空間にアクセスがあったら OS が読み込みを行う。 <li>mmap は並列に動作せず、逐次処理 <li>読み込みが OS 依存となり、環境に左右されやすい <p>並列に動作する I/O の機構が必要である</p> </div> <div class='slide'> <h2>WordCount</h2> <p>サイズの大きいファイルを読み込む例題、WordCount を元に並列 I/O について考える。</p> <p> WordCount は Input としてファイルを受け取り、ファイルの単語数と行数を集計して表示する例題である。 </p> <table> <tr><th><img src="./images/wordcount.png" width="600"></th> <th align="left"> <ul> <li>input ファイルを一定の大きさ分割する <li>読み込んだテキストファイルに対してそれぞれ並列に計算を行う <li>PrintTask が計算結果を集計して出力する </ul> </th> </tr> </table> </div> <div class='slide'> <h2>BlockedRead による I/O の並列化</h2> <p>ファイルを読み込んで、読み込んだファイルに対して並列実行を行う場合、ファイルを分割して処理を行う。</p> <p>よって読み込みの処理自体を分割し、ある程度の大きさ(Block)ごとに読み込みと Task の実行を行う。</p> <p>読み込みの処理自体を分割して行う。これを BlockedRead と呼ぶ。</p> </p> </div> <div class='slide'> <h2>BlockedRead を用いた WordCount</h2> <div align="center"> <img src="./images/blockedread.png" width="600"> </div> <p> BlockedRead を用いて WordCount を行う際、読み込み用の Task と 読み込んだファイルに対して処理を行う Task の2つを生成する。 </p> <p>ファイルを分割して読み込み、 読み込んだファイルに対して WordCount を行う一定数のTask(BlockedTask)を割り当てる。 Task には依存関係を設定する必要があり、図のTask n+1 はBlocked File2 の読み込みを待つ必要がある。 </p> <p>まだ読み込みが終了していない領域に割り当てられた Task が起動してしまう事を防ぐためである。</p> <p>この wait によるロックはオーバーヘッドとなるため、なるべく発生しないことが望ましい。</p> </div> <div class='slide'> <h2>I/O 専用のThread</h2> <p> BlockedRead の依存関係による wait はなるべく発生しないことが望ましい。 そのため、BlockedRead は連続で ReadTask の起動を行う必要がある。 </p> <p> Cerium には SPE_ANY という Thread があり、この Thread で Task の実行を行うと自動で実行するコアを割り振る。 しかし、SPE_ANY で BlockedRead を実行すると BlockedRead 間に別の Task が割り込んでしまう場合がある。 </p> <div align="center"> <img src="./images/speblockedread.png" width="700"> </div> <p>TaskBlock の依存関係によっては wait がかかってしまう。そこで、I/O 専用の Thread を作成した。</p> </div> <div class='slide'> <h2>I/O 専用のThread</h2> <p> IO 専用の Thread を作成したが、それだけでは問題は解決しない場合がある。 IO thread 内では割り込みが生じる可能性はないが、thread レベルで割り込みが起きる可能性がある。 IO thread-SPE_ANY-IO Thread のような実行順序となる場合である。 </p> <div align="center"> <img src="./images/iothread.png" width="700"> </div> <p> そのため、pthread_getschedparam() という POSIX スレッドの API を用いて IO Thread の priority を高く設定した。 IO Thread は必ず連続で行われることになる。 </p> </div> <div class='slide'> <h2>実験環境</h2> <table border="0" style="font-size:25px;"> <tr bgcolor="palegreen"> <th align="center">Model</th><th align="center">MacPro Mid 2010</th> </tr> <tr bgcolor="dbffa3"> <th align="left" >CPU</th><th align="left">6-core Intel Xeon@2.66GHz</th> </tr> <tr bgcolor="palegreen"> <th align="left">Serial-ATA Device</th><th align="left">HDD ST4000VN000-1H4168</th> </tr> <tr bgcolor="dbffa3"> <th align="left">Memory</th><th align="left">16GB</th> </tr> <tr bgcolor="palegreen"> <th align="left">OS</th><th align="left">MacOSX 10.10.1</th> </tr> <tr bgcolor="dbffa3"> <th align="left">Graphics</th><th align="left">NVIDIA Quadro K5000 4096MB</th> </tr> </table> <hr> <table border="0" style="font-size:25px;"> <tr bgcolor="palegreen"> <th align="center">Model</th><th align="center">MacPro Late 2013</th> </tr> <tr bgcolor="dbffa3"> <th align="left" >CPU</th><th align="left">6-core Intel E5@3.5GHz</th> </tr> <tr bgcolor="palegreen"> <th align="left">Serial-ATA Device</th><th align="left">Apple SSD SM0256</th> </tr> <tr bgcolor="dbffa3"> <th align="left">Memory</th><th align="left">16GB</th> </tr> <tr bgcolor="palegreen"> <th align="left">OS</th><th align="left">MacOSX 10.10.1</th> </tr> <tr bgcolor="dbffa3"> <th align="left">Graphics</th><th align="left">AMD FireProD700 6144MB</th> </tr> </table> <p> MacPro 2010 と MacPro 2013 で実験を行った。 MacPro 2013 がより新しいモデルで、クロック数が高く、SSDを使用している。 </p> </div> <div class='slide'> <h2>WordCount によるマルチコア CPU における並列実行のベンチマーク</h2> <table><tr align="left"> <th><img src="./images/word_count_multicore.png" width="600"> </th> <th> <p>2つの実験環境でコア数に対する実行時間の測定を行った。</p> <p> MacPro 2010 において 6CPU を使用した場合、 1CPU を使用した場合に比べて<font color="red"> 5.0 倍</font>の速度向上が見られた。 </p> <p> MacPro 2013 においては 6CPU を使用した場合、 1CPU を使用した場合に比べて<font color="red"> 5.2 倍</font>の速度向上が見られた。 </p> <p>計算機のコア数である 6CPU までは充分に並列度を維持する事ができた。</p> </th> </tr></table> </div> <div class='slide'> <h2>DMA の prefecth に関するベンチマーク </h2> <table><tr align="left"> <th><img src="./images/dmabench.png" width="600"> </th> <th> <p> DMA 転送の prefetch 機能を使用した場合(prefetch)と 使用しなかった場合(no_prefetch)について測定を行った。 </p> <p> 測定の結果、prefetch を使用すると CPU 数が1の場合は<font color="red">1.17%</font>、 CPU 数が6の場合は<font color="red">1.63%</font>の性能向上が見られた。 6CPU までは prefetch を使用した場合の性能が高く、6CPU を超えるとほぼ同じ性能となった。 </p> </th> </tr></table> </div> <div class='slide'> <h2>データ並列実行のベンチマーク</h2> <table><tr align="left"> <th><img src="./images/wordcount_dataparallel.png" width="600"> </th> <th> <p> データ並列実行に関して、マルチコア CPU 、OpenCL、CUDA について通常実行した場合と データ並列実行した場合に関して WordCount を用いて測定を行った。 </p> <p> マルチコア CPU では<font color="red">1.06 倍</font>の性能向上が見られた。 GPU に関しては劇的な性能向上が見られ、OpenCL は<font color="red"> 115 倍</font>、 CUDA は<font color="red"> 14 倍</font>の性能が向上した。 この結果から GPGPU を行う際はデータ並列による実行が必須であることがわかる。 </p> <p> 全体的に性能は向上したが、マルチコア CPU に比べて<font color="blue"> GPU の性能が出ていない</font>。 </p> </th> </tr></table> </div> <div class='slide'> <h2>FFT による GPGPU のベンチマーク(MacPro2010)</h2> <table><tr align="left"> <th><img src="./images/fft_firefly.png" width="600"> </th> <th> <p> FFT により マルチコア CPU、CUDA、OpenCL について測定を行った。 CUDAは 1CPU と比べて<font color="red">3.5倍</font>、 6CPU と比べて<font color="red">1.1倍</font>の性能向上が見られた。 </p> <p> OpenCL に関しては、1CPU と比べて<fonr color="red">2.75倍</fonr>の性能向上が確認できたが、 6CPU と比べると<font color="blue">0.76 倍の性能低下</font>が見られた。 OpenCL のみで FFT を行った場合と比べても<font color="blue">0.76倍</font>の性能低下が見られた。 </p> </th> </tr></table> </div> <div class='slide'> <h2>FFT による GPGPU のベンチマーク(MacPro2013)</h2> <table><tr align="left"> <th><img src="./images/fft_dragonfly.png" width="600"> </th> <th> <p> GPU の性能が高い計算機で測定した結果、GPGPU の性能向上が確認できた。 OpenCL が1CPU と比べて<fonr color="red">6倍</fonr>、 6CPU と比べて<font color="red">1.6 倍</font>の性能が出た。 OpenCL のみで FFT を行った場合と比べても同等の性能を発揮することができた。 </p> </th> </tr></table> </div> <div class='slide'> <h2>BlockedRead による並列 I/O のベンチマーク</h2> <table><tr align="left"> <th><img src="./images/io_thread_firefly.png" width="600"> </th> <th> <p> Cerium の従来の読み込み方式である mmap、一般的な file open である read、 更に今回実装した BlockedRead の測定を行った。 BlockedRead に関しては io Thread を使用した場合(BlockedRead_io)と、 使用しない場合(BlockedRead_speany)の測定を行う。 </p> <p> 6CPU において、BlockedRead_IOを使用した場合、mmap に比べて<font color="red">1.1倍</font>、 read に比べて<font color="red">1.58倍</font>、 BlocedRead_speany と比べて <font color="red">1.34 倍</font>の性能向上が見られた。 </p> </th> </tr></table> </div> <div class='slide'> <h2>まとめ</h2> <p> 本研究室で開発している並列プログラミングフレームワーク、Cerium を用いてマルチプラットフォームに対応した プログラミングフレームワークに関する研究を行った。 </p> <p>マルチプラットフォームへの対応として、以下のことを行った。</p> <ul> <li> マルチコア CPU への対応 <li> GPGPU への対応 <li> データ並列実行のサポート <li> 並列 I/O の実装 <li> ベンチマークによる実装した機能の測定 </ul> </div> <div class='slide'> <h2>今後の課題</h2> <ul> <li> DataDependency の追加 <li> GpuScheduler のパイプラインの改良 </ul> </div> <div class='slide'> <h2>DataDependency</h2> <p> 様々なベンチマークを行ったが、特に Sort や WordCount の例題で Task 生成部分の記述が複雑になるという問題が明らかになった。 </p> <p> 例題特有の依存関係と Task を段階的に生成していくための依存関係の両方を記述しなければならず、 その部分が非常に煩雑になっている。 </p> <p> これは Task 自体に依存関係を設定している事が原因と考えられる。 OpenCL や CUDA ではデータの依存関係(DataDependency)により暗黙的に Task 間の依存関係を設定している。 Cerium でも DataDependency により依存関係を記述できることが望ましい。 </div> <div class='slide'> <h2>GpuScheduler のパイプラインの改良</h2> <p> GpuScheduler のパイプラインループ部分が複雑で、可読性を落としている。 TaskList からパラメタを読み出し、GPU の CommandQueue を操作する処理までループに入っており、 メインループの中に復数のループ文があり、処理が複雑になっている。 </p> <p> 現状のように大きなループの中でフレームワークの API を呼び出すのではなく、 マルチコア CPU のパイプラインのように、SchedTask を使用することが望ましい。 Gpu 用の SchedTask を作り、SchedTask 内部の read, write, exec の部分で GPU を制御を行う。 </p> </div> </div> <!-- presentation --> </bodypp> </html>