view presen/index.html @ 29:6b60c1277599 default tip

fix
author Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
date Sun, 12 Jan 2014 09:18:32 +0900
parents d6d545336b5c
children
line wrap: on
line source

<!--
    Google IO 2012 HTML5 Slide Template

    Authors: Eric Bidelman <ebidel@gmail.com>
    Luke Mahé <lukem@google.com>

    URL: https://code.google.com/p/io-2012-slides
  -->
<!DOCTYPE html>
<html>
  <head>
    <title>Google IO 2012</title>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="chrome=1">
    <!--<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">-->
    <!--<meta name="viewport" content="width=device-width, initial-scale=1.0">-->
    <!--This one seems to work all the time, but really small on ipad-->
    <!--<meta name="viewport" content="initial-scale=0.4">-->
    <meta name="apple-mobile-web-app-capable" content="yes">
    <link rel="stylesheet" media="all" href="theme/css/default.css">
    <link rel="stylesheet" media="only screen and (max-device-width: 480px)" href="theme/css/phone.css">
    <base target="_blank"> <!-- This amazingness opens all links in a new tab. -->
    <script data-main="js/slides" src="js/require-1.0.8.min.js"></script>
  </head>
  <body style="opacity: 0">

    <slides class="layout-widescreen">

      <slide class="title-slide segue nobackground">
        <!-- The content of this hgroup is replaced programmatically through the slide_config.json. -->
        <hgroup>
          <h1 data-config-title><!-- populated from slide_config.json --></h1>
          <h2 data-config-subtitle><!-- populated from slide_config.json --></h2>
          <p data-config-presenter><!-- populated from slide_config.json --></p>
        </hgroup>
      </slide>

      <slide>
        <hgroup>
          <h3>研究目的(1/2)</h3>
        </hgroup>
        <article>
          <p>
            当研究室ではPS3およびLinux、
            Mac OSX上で動く並列プログラミングフレームワーク、
            Ceriumの開発・改良を行っている
          </p>
          <p>
            CeriumはGPU上での並列実行に対応している
          <p>
            <font color="red">ヘテロジニアス(異種混合)環境下でのプログラミングをサポート</font>
          </p>
          <img src='images/cerium_resource.png' style="height:300px">
        </article>
      </slide>

      <slide>
        <hgroup>
          <h3>研究目的(2/2)</h3>
        </hgroup>        
        <article>
          <p>
            GPGPUでは通常のマルチコア<font color="red">CPUとは異なる並列プログラミング</font>
            と<font color="red">特別なチューニング</font>が必要となる。
            そこでCeriumを用いてその差を吸収し、自動的なチューニングを可能にする。
          </p>
            チューニングの一環として、以下を可能にした
            <ul>
              <li>Taskのデータ並列実行</li>
              <li>CPUとGPU両方でTaskを実行</li>
            </ul>
            <img src='images/exe_cpu_gpu.png' style="height:300px">
        </article>
      </slide>

      <slide>
        <hgroup>
          <h3>OpenCLによるGPGPUへの対応</h3>
        </hgroup>
        <article>
        <p>
          OpenCLは
          ヘテロジニアス環境での並列計算を支援するフレームワーク
        </p>
        <table  border="0" cellpadding="0" cellspacing="0">
          <tbody>
            <tr>
              <td><img src='images/opencl.png' style="height:120px"></td>
              <td style="font-size:18pt;color:black">
                <p>
                  OpenCLのtaskはkernelと呼ばれ、OpenCL Cという
                  Cに似た独自の言語で記述される
                </p>
              </td>
            </tr>
          </tbody>
        </table>
        <p>          
          <h3 class='yellow'>Ceriumにおいて、CPU/Cell上で実行する場合とGPU上で実行する場合、
            それぞれほぼ同じ形式でkernelを記述できる
          </h3>
        </p>
        </article>
      </slide>


      <slide>
        <hgroup>
          <h3>Kernelの記述</h3>
        </hgroup>
          2つのinputDataの積を取り、outputDataに返す例題Multiply
        <table  border="0" cellpadding="0" cellspacing="0">
          <tbody>
            <tr>
              <td>
                <img src='images/kernel_description.png' style="height:570px">
              </td>
              <td style="font-size:18pt;color:black">
                <p>
                  Taskの処理自体はC/C++の形式なので、同じ記述が可能。
                </p>
                <p>
                  引数の受け取り方が違う。
                  <ul>
                    <li>CPU
                      <dd>rbuf/wbufとしてDataをまとめて受け取っている</dd></li>
                    <li>GPU
                      <dd>1つ1つ個別の変数として受け取っている</dd>
                      <dd>それぞれの変数にOpenCL独自の修飾子が必要</dd></li>
                  </ul>
                  変数で受けるなどしてこの差異を吸収すれば、同じ記述が可能。
                </p>
                
              </td>
            </tr>
          </tbody>
        </table>
      </slide>


      <slide>
        <hgroup>
          <h3>Cerium Task ManagerによるTaskの実行</h3>
        </hgroup>
        <article>
        <table  border="0" cellpadding="0" cellspacing="0">
          <tbody>
            <tr>
              <td><img src='images/createtask.png' style="height:350px"></td>
              <td style="font-size:18pt;color:black">
                <p>
                  TaskManagerと各Threadsの間にはSyncronized Queueがある。</p>
                <p>
                  TaskはTaskManagerからSyncronized Queueに送られる。
                  実行するデバイスに対応したThreadsがQueueからTaskを取得し、
                  並列実行していく。
                </p>
                
                <p>
                  
                </p>

              </td>
            </tr>
          </tbody>
        </table>
        <br>
        <p>
          ユーザが生成したTaskはTaskManagerに送られ、依存関係を解決したあと、
          各Schedulerに送られ並列実行される
        </p>
        </article>
      </slide>
     <slide>
        <hgroup>
          <h3>GPUの特徴</h3>
        </hgroup>
        <article>
          <table  border="0" cellpadding="0" cellspacing="0">
            <tbody>
              <tr>
                <td><img src='images/gpu_arch.png' style="height:400px"></td>
                <td style="font-size:18pt;color:black">
                  <p>
                    GPU上のローカルメモリはCPUとメモリ空間が異なるのでメモリの共有ができない。
                    よって、OpenCLのAPIを用いてデータを転送する必要がある。するとこの転送がネックになる。
                  </p>
                  <p>
                    GPGPUは<font color="red">データの転送が頻繁に起こる</font>ようなTaskは並列度が出づらい。
                  </p>
                </td>
              </tr>
            </tbody>
          </table>
        </article>
      </slide>

     <slide>
       <hgroup>
         <h3>データ転送</h3>
       </hgroup>
       <article>
         <table  border="0" cellpadding="0" cellspacing="0">
            <tbody>
              <tr>
                <td><img src='images/gpu_data_parallel.png' style="height:450px"></td>
                <td style="font-size:18pt;color:black">
                  <p>
                    タスク並列だと、タスクごとにinput data と output data を転送しなければならない
                  </p>
                  <p>
                    データ並列なら全dataをGPUに送ることになる。結果的に転送の回数は減る
                  </p>
                  <p>
                    OpenCLでは、NDRange APIを用いてデータ並列実行を行う
                  </p>
                </td>
              </tr>
            </tbody>
          </table>
       </article>
     </slide>



          <slide>
       <hgroup>
         <h3>OpenCLにおけるデータ並列</h3>
       </hgroup>
       <article>
         <table  border="0" cellpadding="0" cellspacing="0">
            <tbody>
              <tr>
                <td><img src='images/ndrange_arch.png' style="height:500px"></td>
                <td style="font-size:18pt;color:black">
                  <p>
                    データを2、3次元に分割し、分割した部分に対して
                    同一のTaskを割り当て、並列に処理を行う並列化手法
                  </p>
                  <p>
                    CPUからinput/output data をGPUのglobal memoryにコピーし、データを分割
                  </p>
                  <p>分割したデータをWork Itemと呼ぶ</p>
                  <p><font color="red">
                      複数生成されたkernelに対してそれぞれのWork ItemとIDを割り当てる。
                    </font>
                    kernelは割り当てられたIDから自分が計算する範囲を求め、処理を行う。
                  </p>
                </td>
              </tr>
            </tbody>
          </table>
       </article>
     </slide>

      <slide>
        <hgroup>
          <h3>データ並列のための新しいAPI</h3>
        </hgroup>
        <article>
          <table  border="0" cellpadding="0" cellspacing="0">
            <tbody>
              <tr>
                <td>
                  <img src="images/iterate.png" height="450"></img>
                </td>
                <td>
                  <font style="font-size:18pt;color:black">
                    <p>
                      データ並列による実行を行う場合、一つの記述から複数のTaskを生成する必要がある
                    </p>
                    <p>
                      生成した各TaskにIDとinput/output dataを割り当てる「iterate」というAPIを実装する
                    </p>
                    <p>iterate</p>
                    <ul>
                      <li>1つの記述から複数のTaskを生成する</li>
                      <li>生成した複数のTaskにIDとInput/Output Dataを割り当てる</li>
                    </ul>
                    <p>
                      この例だと、Taskの持つidとTaskに割り当てられるデータは
                      1対1で対応している。id=割り当てられたdataのindexとなっている。
                    </p>
                  </font>
                </td>
          </tr></tbody></table>
        </article>
      </slide>

      <slide>
        <hgroup>
          <h3>iterate API</h3>
        </hgroup>
        <article>
          <p>
            input data を二倍してoutput data に返す例題
          </p>
          <img src="images/iterateTaskGen.png" height="250"></img>
          <p>
            iterate(length)とすることで、TaskManagerがデータ並列用にTaskを生成
          </p>
          <p>
            この例だとlength個のTaskが生成され、各Taskに0~length-1までのID(index)を割り振る
          </p>
            各Taskはinput dataの自分が割り当てられた要素に対して処理を行う
          </p>
        </article>
      </slide>


      <slide>
        <hgroup>
          <h3>iterate(Kernel)</h3>
        </hgroup>
        <article>
          <img src="images/source/iterate_kernel.png" height="300"></img>
          <p>
            MultiCoreではschedulerの持つメンバ変数x、OpenCLはget_global_idというAPIを用いて、
            自分に割り振られたid(index)を取得する。その後、そのindexに対して処理を行う。
          </p>
          <p>
            iterateにおいても、CeriumとOpenCLはほぼ同じ形式でTaskの記述が可能である。
          </p>
        </article>
      </slide>

      <slide>
        <hgroup>
          <h3>iterateの実装</h3>
        </hgroup>
        <article>
          <img src="images/source/iterate.png" height="280"></img>
          <p>渡されたlengthはwork item の要素数となる。</p>
          <p>taskにデータ分割のためのdata(dimension, や workitem size)をsetする。</p>
          <p>
            Schedulerはtaskが持ってるdataを元にtaskを複数生成し、idを割り当てる。
          </p>
        </article>
      </slide>

      <slide>
        <hgroup>
          <h3>iterateの実装(多次元)</h3>
        </hgroup>
        <article>
          <img src="images/source/iterate_multidim.png" height="300"></img>
          <p>
            引数を複数渡せば多次元のデータ分割ができる。3次元までサポートする。
          </p>
        </article>
      </slide>

      <slide>
        <hgroup>
          <h3>CeriumにおけるGPU上でのデータ並列</h3>
        </hgroup>
        <br>
        <p>
          GpuSchedulerがOpenCLのAPIを呼び出し、GPUの制御を行う</p>
        <p>
          TaskManagerから受け取ったTaskは必要なパラメータを各種持っている
        </p>
        <article>
          <img src="images/source/GpuScheduler.png" height="120"></img>
          <table  border="2" style="font-size:18pt;">
            <tbody>
              <h3 class="yellow">Taskの持つメンバ変数</h3>
              <tr>
                <td>dim</td>
                <td>データを分割する次元数</td>
              </tr>
              <tr>
                <td>x</td>
                <td>x座標の要素数</td>
              </tr>

              <tr>
                <td>y</td>
                <td>y座標の要素数</td>
              </tr>

              <tr>
                <td>z</td>
                <td>z座標の要素数</td>
              </tr>
            </tbody>
          </table>

        </article>
      </slide>      

     <slide>
        <hgroup>
          <h3>ベンチマーク</h3>
        </hgroup>
          <h3 class="yellow">実験環境</h3>
          <table>
            <tbody>
              <tr>
                <td>OS</td><td>MacOS 10.9.1</td>
              </tr>
              <tr>
                <td>CPU</td><td>2*2.66GHz 6-CoreIntel Xeon</td>
              </tr>
              <tr>
                <td>Memory</td><td>16GB</td>
              </tr>
              <tr>
                <td>Compiler</td><td>Apple LLVM version 5.0<br>(clang-500.2.79)</td>
              </tr>
              <tr>
                <td>GPU</td><td>AMD ATI Radeon HD 5870 1024MB</td>
              </tr>
            </tbody>
          </table>
          <p>
          </p>
          <h3 class="yellow">時間測定の方法</h3>
          <ul>
            <li>CPU</li>
            RDTSC命令を用いて、CPUからタイムスタンプカウンタを取得し、
            時間の測定を行っている
            <li>GPU</li>
            OpenCLのAPI(clGetEventProfilingInfo)を用いて測定
          </ul>
          <p>
            Taskがtask_start_time, task_end_timeを持っていて、
            SchedulerがTaskを開始・終了した時に値を書き込む。
          </p>

     </slide>

     <slide>
        <hgroup>
          <h3>ベンチマーク</h3>
        </hgroup>
        <table >
          <tbody>
            <tr>
              <td> <!--  benchmark -->
                <img src="images/bench_mark_busy_time.png" height="300"></img>
              </td> <!-- /benchmark -->
              <td>  <!-- system env -->
                <h3 class="yellow">FFT</h3>
                <font size="5">
                  <p>
                    フーリエ変換と周波数フィルタによる、
                    512*512の画像への処理をデータ並列で行う例題
                  </p>
                  <h3 class="yellow">結果</h3>
                  <font size="5">
                    <p>
                      GPU 実行が1 coreのCPUよりも4.8倍、2 Coreよりも2.7倍の実行速度。
                      CPUはどのコアもBusy TimeとRun Timeに大きな差は無いが、
                      GPUは大きく差が開いた。
                    </p>
                  </font>
              </td> <!--system env  -->
            </tr>
          </tbody>
        </table>
        <dl>
        <ul>
          <li><font color="red">iterateを使用すると、GPU側が劇的に速い</font></li>
          <li>GPUはBusy Time以外の時間に大きく処理を割いている</li>
          <dd>おそらくデータの転送(IO)部分</dd>
        </ul>
        </dl>
      </slide>

     <slide>
        <hgroup>
          <h3>CPUとGPUの同時実行</h3>
        </hgroup>
        <article>
        <table >
          <tbody>
            <tr>
              <td> <!--  image -->
                <img src="images/exe_on_cpu_and_gpu.png" height="300"></img>
              </td> <!-- /imafe -->
              <td>  <!-- describe -->
                <font size="5">
                  <p>
                    さらなる改良として、CPU上とGPU上での同時実行を可能にした。
                  </p>
                  <p>
                    GPUに比べてCPUの演算能力は小さかったが、
                    同時実行できれば演算資源の1つとして活用できる
                  </p>
                </font>
              </td> <!-- describev  -->
            </tr>
          </tbody>
        </table>
        <br>
        <p>
          CPUとGPUの同時実行は、実行するTaskに対してset_cpu(ANY_ANY)とすれば良い
        </p>
        <p>
          TaskはCPUとGPU、交互に割り振られる
        </p>
        </article>
      </slide>
     
      <slide>
        <hgroup>
          <h3>ベンチマーク</h3>
        </hgroup>
        <article>
          <img src="images/bench_mark_hetero.png" height="350"></img>
          <h3 class="yellow">結果</h3>
          <p>
            現段階ではSchedulingを行ってないため、GPUやCPUを単体で動かした時よりも遅くなる。
          </p>
          <p>
            CPUとGPUは実行速度に差が出る場合がある。
            Taskの計算内容によってはどちらかのアーキテクチャに任せた方が良い。
            それを確認するベンチマークを動かす。
          </p>
     </font>
     </article>
     </slide>
     
     
     <slide>
       <hgroup>
         <h3>ベンチマーク</h3>
       </hgroup>
       <article>
         <img src="images/bench_mark_each_task.png" height="350"></img>
          <p>
            FFTはSpinFactやButterfly演算等、様々なTaskで構成されている。
            それぞれのTaskについて、実行時間を計測した。
          </p>
          <p>
            大体のTaskはGPUの方が速いが、SpinFactのTaskに関してはCPUの方が実行速度が速い。
          </p>
        </article>
      </slide>

      <slide>
        <hgroup>
          <h3>新たに実装するScheduling手法の提案</h3>
        </hgroup>
        <article>
          <table >
            <tbody>
              <tr>
                <td>
                  <img src="images/decide_weight.png" height="150"></img>
                </td>
                <td style="font-size:18pt;color:black">
                  並列実行するTaskをCPUとGPUで事前に一度実行し、実行時間を測定する。
                  それぞれの実行時間の割合で重みをつける。
                </td>
              </tr>
              <tr>
                <td>
                  <img src="images/select_arch.png" height="200"></img>
                </td>
                <td style="font-size:18pt;color:black">
                  <p>
                    それぞれの重みからCPU実行とGPU実行のどちらに適しているか判断する
                  </p>
                </td>
              </tr>
            </tbody>
          </table>
          
        </article>
      </slide>

      <slide>
        <hgroup>
          <h3>新たに実装するScheduling手法の提案</h3>
        </hgroup>
        <article>
          <p>
            更に、CPUとGPUでTaskが同時に終了するようにSchedulingを行いたい。
          </p>
          <table >
            <tbody>
              <tr>
                <td>
                  <img src="images/decide_weight2.png" height="150"></img>
                </td>
                <td style="font-size:18pt;color:black">
                  全てのTaskがCPUの二倍、GPUの方が実行速度が早い場合
                </td>
              </tr>
              <tr>
                <td>
                  <img src="images/select_arch2.png" height="180"></img>
                </td>
                <td style="font-size:18pt;color:black">
                  <p>
                    それぞれのTaskを得意とするアーキテクチャに全て割り振るのではなく、
                    RunTimeが最小になるように割り振る
                  </p>
                </td>
              </tr>
            </tbody>
          </table>
          
        </article>
      </slide>

      <slide>
        <hgroup>
          <h3>まとめ</h3>
        </hgroup>
        <article>
        <ul>
          <li>Cerium Task Managerをデータ並列に対応</li>
          <li>FFTによるデータ並列実行のベンチマーク</li>
          <li>CPUとGPUでのTaskの同時実行に対応</li>
          <li>同時実行時のTaskのScheduling手法の提案</li>
        </ul>
        <h3 class="yellow">今後の課題</h3>
        <ul>
          <li>提案したSchedulingの手法を実装/ベンチマーク</li>
          <li>ベンチマークに使用する例題の追加</li>
          <li>GPUのSchedulerにパイプライン機構の導入</li>
        </ul>
        </article>
      </slide>

      <!--
      <slide>
        <hgroup>
          <h3>ベンチマーク結果の考察</h3>
        </hgroup>
        <article>
        <p>
          性能向上は見られたが、CPUと比べると未だ差が開いている<br>
          GPU向けに適切なチューニングが今後の課題となる
        </p>
        <ul>
          <li>CPUとGPUの性能差</li>
          <li>data送受信のオーバーヘッド</li>
        </ul>
        <br>
        <h3 class="yellow">改善案</h3>
        <p>
          データ並列によるkernelの実行
        </p>
        </article>
      </slide>
      <slide>
        <hgroup>
          <h3>OpenCLにおけるデータ並列</h3>
        </hgroup>
        <article>
          <table  border="0" cellpadding="0" cellspacing="0">
            <tbody>
              <tr>
                <td><img src='images/ndrange_arch.png' style="height:450px"></td>
                <td>
                  <font style="font-size:18pt;color:black">
                  <p>データを2、3次元に分割し、分割した部分に対して並列処理する並列化手法</p>
                  <p>
                    CPUからinput/output data をGPUのglobal memoryにコピーし、データを分割</p>
                  <p>分割したデータをWork Itemと呼ぶ</p>
                  <p><font color="red">
                      複数生成されたkernelに対してそれぞれのWork ItemとIDを割り当てる。
                    </font>
                    kernelは割り当てられたIDから自分が計算する範囲を求め、処理を行う。
                  </p>
                </td>
              </tr>
            </tbody>
          </table>
        </article>
      </slide>


      <slide>
        <hgroup>
          <h3>Cerium におけるデータ並列(Task生成)</h3>
        </hgroup>
        <article>
	      <p>Twiceというinput data を2倍にしてoutput data に返す例題</p>
<pre class="prettyprint" data-lang="main.cc">
for (int c=0; c < length;c++) {
    twice[c] = manager->create_task(Twice);
    twice[c]->set_param(0,c,sizeof(int));
    twice[c]->set_inData(0, indata, sizeof (int)*length);
    twice[c]->set_outData(0, outdata, sizeof (int)*length);
    Twice[c]->set_cpu(CPU);
    twice[c]->spawn();
}
</pre>
<table  border="2" style="font-size:18pt;">
  <tbody>
    <tr>
      <td>create_task()</td>
      <td>Taskを作成する。input data等を設定した後、spawnする。</td>
    </tr>
    <tr>
      <td>set_param()</td>
      <td>任意にパラメタをsetする。ここでは各Taskにidを送っている。</td>
    </tr>
    <tr>
      <td> set_inData(), set_outData()</td>
      <td >input data, output dataをsetする</td>
    </tr>
    <tr>
      <td> set_cpu()</td>
      <td >taskを実行するデバイスの指定</td>
    </tr>
  </tbody>
</table>
        </article>
      </slide>
      

      <slide>
        <hgroup>
          <h3>Cerium におけるデータ並列(Taskの記述)</h3>
        </hgroup>
        <article>
<pre class="prettyprint" data-lang="twice.cc">
    int id = s->get_param(0);
    output_data[id] = input_data[id] * 2;
</pre>
<ul>
  <li>get_param() :set_paramした値を取得する。ここではidを取得している </li>
  <li>取得したidから自分が処理する範囲を計算し、処理する</li>
</ul>
        </article>
      </slide>
      -->
      <slide class="backdrop"></slide>  
</slides>

    <script>
      var _gaq = _gaq || [];
      _gaq.push(['_setAccount', 'UA-XXXXXXXX-1']);
      _gaq.push(['_trackPageview']);

      (function() {
      var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
      ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
      var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
      })();
    </script>

    <!--[if IE]>
        <script src="http://ajax.googleapis.com/ajax/libs/chrome-frame/1/CFInstall.min.js"></script>
        <script>CFInstall.check({mode: 'overlay'});</script>
        <![endif]-->
  </body>
</html>