O slideshow foi denunciado.
Utilizamos seu perfil e dados de atividades no LinkedIn para personalizar e exibir anúncios mais relevantes. Altere suas preferências de anúncios quando desejar.

Slide

963 visualizações

Publicada em

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

Publicada em: Engenharia
  • Entre para ver os comentários

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/

×