Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Slide

952 views

Published on

OpenCL +alpha.
(1) OpenCL + I/O
(2) trying kinds of high-level languages for OpenCL

Published in: Engineering
  • Login to see the comments

Slide

  1. 1. OpenCLやってみた + α みよし たけふみ わさらぼ 2016/08/24
  2. 2. 動機 OpenCL あまり使ったことないし,やってみるか 評価版のライセンスをいただいた
  3. 3. DE0-nano-SoCでOpenCL Atlas のサンプル (Mandelbrot) からはじめるのがよい? buildroot な Linux 環境 いくつかのユーティリティを追加 dhcpcd,ssh,ImageMagick,lighthttpd FPGA は/dev/acl0 に見えている OpenCL Mandelbrot Demo on Altera を読む&試す@Qiita
  4. 4. +α FPGA なので I/O たたきたい OpenCL 面倒.より高級な言語で使える?
  5. 5. OpenCLでI/O叩く Altera の I/O チャネルが用意されてる HDL 側のレジスタに OpenCL で値を出力→ LED へ データムーバができれば,後は何とかなりそう OpenCL Kernel Register FIFO LED CPU Main Memory ドキュメントを参考に, OpenCL コードとボード定義を作ってみる
  6. 6. I/OチャネルでI/Oする OpenCL のコード.読んだり書いたり. channel uint inCtrlCh __attribute__ (( io (” aux_ctrl_in ” ) ) ) ; channel uint outCtrlCh __attribute__ (( io (”aux_ctrl_out” ) ) ) ; channel uint inDataCh __attribute__ (( io (”aux_data_in” ) ) ) ; channel uint outDataCh __attribute__ (( io (”aux_data_out” ) ) ) ; __kernel void ctrl_write_read ( int a , __global int * r e s t r i c t b ){ write_channel_altera ( outCtrlCh , a ) ; *b = read_channel_altera ( inCtrlCh ) ; } __kernel void data_write_read ( __global int * r e s t r i c t a , __global int * r e s t r i c t b ){ for ( int i = 0; i < 256; i++){ write_channel_altera (outDataCh , a [ i ] ) ; b [ i ] = read_channel_altera ( inDataCh ) ; } }
  7. 7. データの読み書きを確認
  8. 8. LEDが光ったよ
  9. 9. カメラをつないでみよう
  10. 10. カメラをつないでみよう 定番,OV7670 をカメラに直結 SCCB 経由でのレジスタ設定を OpenCL 経由で 設定しないと動かない 結構面倒.読んだり書いたり. プリミティブ操作をカーネルで実装 1 フレームのデータをキャプチャしてメインメモリに YUV → RGB の SW 実装 v.s. HW 実装で処理時間を比較
  11. 11. システム構成 ov7670_ctrl ov7670_data RegisterFIFO ov7670 _capture sccb_iface OV7670 OpenCL CPU Main Memory Cynclon V SoC YUV422 YUV422 or RGB Y0 U Y1 V
  12. 12. カメラ画像取得 - 取得するだけ __kernel void ov7670_capture ( __global unsigned int * r e s t r i c t buf ){ const int s i z e = 320 * 480; for ( int i = 0; i < s i z e ; i++){ int d = read_channel_altera ( inDataCh ) ; buf [ i ] = d ; } } Y0UY1V の順でデータを書き出す YUV->RGB はソフトウェアで変換
  13. 13. カメラ画像取得 - 取得しつつRGBに #define RANGE(x) (x < 16 ? 16 : x > 235 ? 235 : x) __kernel void ov7670_capture ( __global unsigned char * r e s t r i c t buf ){ const int s i z e = 320 * 480; for ( int i = 0; i < s i z e ; i++){ int d = read_channel_altera ( inDataCh ) ; int y0 = (d >> 24) & 0x000000FF ; int cb = (d >> 16) & 0x000000FF ; int y1 = (d >> 8) & 0x000000FF ; int cr = (d >> 0) & 0x000000FF ; int r0 , g0 , b0 ; r0 = y0+140750*(cr −128)/100000; g0 = y0− 34550*(cb−128)/100000−71690*(cr −128)/100000; b0 = y0+177900*(cb −128)/100000; int r1 , g1 , b1 ; . . . int ptr ; ptr = 3*(640*480−1−(2* i ) ) ; buf [ ptr +0] = ( unsigned char )(RANGE(b0 ) ) ; buf [ ptr +1] = ( unsigned char )(RANGE(g0 ) ) ; buf [ ptr +2] = ( unsigned char )(RANGE( r0 ) ) ; ptr = 3*(640*480−1−(2* i +1)); . . . } }
  14. 14. 動いたよ capture: 41.994ms conv: 14.888ms write bmp: 7.602ms total: 64.484ms capture: 36.725ms write bmp: 7.614ms total: 44.339ms ※ SW 側は,データ転送の工夫で性能改善の余地はある
  15. 15. +α FPGA なので I/O たたきたい OpenCL 面倒.より高級な言語で使える?
  16. 16. もっと高級言語で!! C/C++とか,よく使いこなせない カーネルとホストコード両方書くの面倒... 世の中には OpenCL を生成するコンパイラが
  17. 17. たくさんある
  18. 18. Harlanを試してみた https://github.com/eholk/harlan Scheme で書かれた処理系 入力も Scheme っぽい感じで ホスト/カーネル両方書ける
  19. 19. コードの例 test/dot-product.kfc ; ; Dense dot product between two vectors . (module ( define (main) ( l e t ((X ( vector 1 2 3 4)) (Y ( vector 4 3 2 1))) ( l e t (( dot ( reduce + ( kernel (( x X) (y Y)) (* x y ) ) ) ) ) ( p r i n t l n dot ) ( assert (= dot 20)) 0)))) コンパイル ./ harlanc −g −v test /dot−product . kfc
  20. 20. 出力されたカーネル(抜粋) __kernel void harlan_main_282 ( region_ptr danger_vector_259 , region_ptr kern_256 , int stride_20 , region_ptr y_32 , region_ptr x_33 , void __global * rk_143_285 , void __global * rv_53_284 , void __global * rv_63_283) { region __global * rk_143 = (( region __global *)( rk_143_285 ) ) ; region __global * rv_53 = (( region __global *)( rv_53_284 ) ) ; region __global * rv_63 = (( region __global *)( rv_63_283 ) ) ; { int __global * retval_260 = (&((( int __global *)( get_region_ptr (rk_143 , ( kern_256 ) + int i_34 = get_global_id (0); int x_36 = (( int __global *)( get_region_ptr (rv_63 , (x_33) + ( 8 ) ) ) ) [ i_34 ] ; int y_35 = (( int __global *)( get_region_ptr (rv_53 , (y_32) + ( 8 ) ) ) ) [ i_34 ] ; int t_37 = (x_36) * (y_35 ) ; int reduce_dindex_40 = ( i_34 ) + ( stride_20 ) ; int stepv_39 = stride_20 ; int stopv_38 = *(( int __global *)( get_region_ptr (rv_63 , x_33 ) ) ) ; while (( reduce_dindex_40 ) < ( stopv_38 )) { int x_42 = (( int __global *)( get_region_ptr (rv_63 , (x_33) + ( 8 ) ) ) ) [ reduce_dind int y_41 = (( int __global *)( get_region_ptr (rv_53 , (y_32) + ( 8 ) ) ) ) [ reduce_dind t_37 = (t_37) + (( x_42) * (y_41 ) ) ; reduce_dindex_40 = ( reduce_dindex_40 ) + ( stepv_39 ) ; } *retval_260 = t_37 ; } }
  21. 21. 出力されたホストコード(抜粋) . . . c l : : kernel harlan_main_282_288 = g_prog . createKernel (”harlan_main_282” ) ; int dim_289 = stride_20 ; unmap_region ( rk_143 ) ; unmap_region ( rv_53 ) ; unmap_region ( rv_63 ) ; harlan_main_282_288 . setArg (0 , danger_vector_259 ) ; harlan_main_282_288 . setArg (1 , kern_256 ) ; harlan_main_282_288 . setArg (2 , stride_20 ) ; harlan_main_282_288 . setArg (3 , y_32 ) ; harlan_main_282_288 . setArg (4 , x_33 ) ; harlan_main_282_288 . setArg (5 , get_cl_buffer ( rk_143 ) ) ; harlan_main_282_288 . setArg (6 , get_cl_buffer ( rv_53 ) ) ; harlan_main_282_288 . setArg (7 , get_cl_buffer ( rv_63 ) ) ; g_queue . execute ( harlan_main_282_288 , dim_289 ) ; . . . int dot_48 = if_res_272 ; pri nt (dot_48 ) ; a s s e r t (( dot_48) == (20)); . . .
  22. 22. コンパイルしてみると いくつか手を入れないとだめ オフラインコンパイルに対応 $記号が使えない ← 簡単なスクリプトで変換する程度 _も好ましくない ホストコードの DEVICE_TYPE の修正 clCreateProgramWithBinary に対応 あとは Altera OpenCL ツールでコンパイル aoc でハードウェア側を合成 ホストコードは arm-linux-gnuebahf-を使う
  23. 23. 動いた
  24. 24. 評価とか... 続きは後日 (Qiita? )
  25. 25. まとめ 簡単な I/O の追加をテスト → カメラの接続 “組み込み” にも嬉しいかも 汎用の CPU/FPGA 協調動作環境として メインメモリが簡単に使える ソフトウェア/CPU との連携も I/O アクセス直結の処理は見通しよく書ける IO チャネルアクセスが一箇所は,ちょっと面倒 OpenCL では書かないのが吉? それ,Synthesijer で...? 沢山チャネルはやして外でアービトレーション? より高級言語で Altera OpenCL を使う できる (できた) 記号の使い方に注意が必要 最適化とかはこれから考えてみる Iroha でよいのでは?
  26. 26. ところで,Traxとかどうですか? http://trax-fit2016.github.io/contest/

×