Top Banner
OpenCL やってみた + α みよし たけふみ わさらぼ 2016/08/24
26

Slide

Jan 10, 2017

Download

Engineering

Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Slide

OpenCLやってみた + α

みよし たけふみ

わさらぼ

2016/08/24

Page 2: Slide

動機

I OpenCLあまり使ったことないし,やってみるかI 評価版のライセンスをいただいた

Page 3: Slide

DE0-nano-SoCでOpenCLAtlasのサンプル (Mandelbrot)からはじめるのがよい?

I buildrootな Linux環境I いくつかのユーティリティを追加

I dhcpcd,ssh,ImageMagick,lighthttpdI FPGAは/dev/acl0に見えているI OpenCL Mandelbrot Demo on Alteraを読む&試す@Qiita

Page 4: Slide

I FPGAなので I/OたたきたいI OpenCL面倒.より高級な言語で使える?

Page 5: Slide

OpenCLで I/O叩くI Alteraの I/Oチャネルが用意されてるI HDL側のレジスタにOpenCLで値を出力→ LEDへI データムーバができれば,後は何とかなりそう

OpenCLKernel

Register

FIFO

LED

CPUMain Memory

ドキュメントを参考に,

OpenCLコードとボード定義を作ってみる

Page 6: Slide

I/Oチャネルで I/OするOpenCLのコード.読んだり書いたり.

channel u in t inCtr lCh __attribute__ (( i o ( ” aux_ctr l_in ” ) ) ) ;channel u in t outCtr lCh __attribute__ (( i o ( ” aux_ctr l_out ” ) ) ) ;channel u in t inDataCh __attribute__ (( i o ( ”aux_data_in” ) ) ) ;channel u in t outDataCh __attribute__ (( i o ( ”aux_data_out” ) ) ) ;

__kernel void ct r l_wr i te_read ( i n t a ,__global i n t * r e s t r i c t b ){

wr i te_channe l_a l te ra ( outCtrlCh , a ) ;*b = read_channel_altera ( inCtr lCh ) ;

}

__kernel void data_write_read ( __global i n t * r e s t r i c t a ,__global i n t * r e s t r i c t b ){

f o r ( i n t i = 0; i < 256; i++){wr i te_channe l_a l te ra (outDataCh , a [ i ] ) ;b [ i ] = read_channel_altera ( inDataCh ) ;

}}

Page 7: Slide

データの読み書きを確認

Page 8: Slide

LEDが光ったよ

Page 9: Slide

カメラをつないでみよう

Page 10: Slide

カメラをつないでみよう

I 定番,OV7670をカメラに直結I SCCB経由でのレジスタ設定をOpenCL経由で

I 設定しないと動かないI 結構面倒.読んだり書いたり.I プリミティブ操作をカーネルで実装

I 1フレームのデータをキャプチャしてメインメモリにI YUV→ RGBの SW実装 v.s. HW実装で処理時間を比較

Page 11: Slide

システム構成

ov7670_ctrl

ov7670_data

Register

FIFO ov7670

_capture

sccb_ifaceOV7670

OpenCL

CPUMain Memory

Cynclon V SoC

YUV422

YUV422 or RGB

Y0 U Y1 V

Page 12: Slide

カメラ画像取得 - 取得するだけ

__kernelvoid ov7670_capture ( __global unsigned i n t * r e s t r i c t buf ){

const i n t s i z e = 320 * 480;f o r ( i n t i = 0; i < s i z e ; i++){

i n t d = read_channel_altera ( inDataCh ) ;buf [ i ] = d ;

}}

I Y0UY1Vの順でデータを書き出すI YUV->RGBはソフトウェアで変換

Page 13: Slide

カメラ画像取得 - 取得しつつRGBに#def ine 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 i n t s i z e = 320 * 480;f o r ( i n t i = 0; i < s i z e ; i++){

i n t d = read_channel_altera ( inDataCh ) ;i n t y0 = (d >> 24) & 0x000000FF ;i n t cb = (d >> 16) & 0x000000FF ;i n t y1 = (d >> 8) & 0x000000FF ;i n t cr = (d >> 0) & 0x000000FF ;i n t 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;i n t r1 , g1 , b1 ;. . .i n t pt r ;p t r = 3*(640*480−1−(2* i ) ) ;buf [ p t r+0] = ( unsigned char ) (RANGE(b0 ) ) ;buf [ p t r+1] = ( unsigned char ) (RANGE(g0 ) ) ;buf [ p t r+2] = ( unsigned char ) (RANGE( r0 ) ) ;pt r = 3*(640*480−1−(2* i +1));. . .

}}

Page 14: Slide

動いたよ

I capture: 41.994msI conv: 14.888msI write bmp: 7.602msI total: 64.484ms

I capture: 36.725msI write bmp: 7.614msI total: 44.339ms

※ SW 側は,データ転送の工夫で性能改善の余地はある

Page 15: Slide

I FPGAなので I/OたたきたいI OpenCL面倒.より高級な言語で使える?

Page 16: Slide

もっと高級言語で!!

I C/C++とか,よく使いこなせないI カーネルとホストコード両方書くの面倒...

I 世の中にはOpenCLを生成するコンパイラが

Page 17: Slide

たくさんある

Page 18: Slide

Harlanを試してみた

https://github.com/eholk/harlanI Schemeで書かれた処理系I 入力も Schemeっぽい感じでI ホスト/カーネル両方書ける

Page 19: Slide

コードの例

test/dot-product.kfc; ; Dense dot product between two vec to r s .

(module( de f i n e (main )

( l e t ( (X ( vector 1 2 3 4))(Y ( vector 4 3 2 1)))

( l e t ( ( dot ( reduce + ( ke rne l ( ( x X) ( y Y))(* x y ) ) ) ) )

( p r i n t l n dot )( as se r t (= dot 20))0 ) ) ) )

コンパイル

. / har lanc −g −v te s t /dot−product . k fc

Page 20: Slide

出力されたカーネル (抜粋)

__kernel void harlan_main_282 ( reg ion_ptr danger_vector_259 , reg ion_ptr kern_256 ,i n t str ide_20 , reg ion_ptr y_32 , reg ion_ptr x_33 ,void __global * rk_143_285 , void __global * rv_53_284 , void __global * rv_63_283)

{reg ion __global * rk_143 = (( reg ion __global *)( rk_143_285 ) ) ;r eg ion __global * rv_53 = (( reg ion __global *)( rv_53_284 ) ) ;r eg ion __global * rv_63 = (( reg ion __global *)( rv_63_283 ) ) ;{

i n t __global * retva l_260 = (&((( i n t __global *)( get_region_ptr ( rk_143 , ( kern_256 ) + ( 8 ) ) ) ) [ get_global_id ( 0 ) ] ) ) ;

i n t i_34 = get_global_id ( 0 ) ;i n t x_36 = (( i n t __global *)( get_region_ptr ( rv_63 , (x_33) + ( 8 ) ) ) ) [ i_34 ] ;i n t y_35 = (( i n t __global *)( get_region_ptr ( rv_53 , (y_32) + ( 8 ) ) ) ) [ i_34 ] ;i n t t_37 = (x_36) * (y_35 ) ;i n t reduce_dindex_40 = ( i_34 ) + ( st r ide_20 ) ;i n t stepv_39 = str ide_20 ;i n t stopv_38 = *(( i n t __global *)( get_region_ptr ( rv_63 , x_33 ) ) ) ;whi le ( ( reduce_dindex_40 ) < ( stopv_38 ))

{i n t x_42 = (( i n t __global *)( get_region_ptr ( rv_63 , (x_33) + ( 8 ) ) ) ) [ reduce_dindex_40 ] ;i n t y_41 = (( i n t __global *)( get_region_ptr ( rv_53 , (y_32) + ( 8 ) ) ) ) [ reduce_dindex_40 ] ;t_37 = ( t_37) + (( x_42) * (y_41 ) ) ;reduce_dindex_40 = ( reduce_dindex_40 ) + ( stepv_39 ) ;

}* retva l_260 = t_37 ;

}}

Page 21: Slide

出力されたホストコード (抜粋)

. . .c l : : k e rne l harlan_main_282_288 = g_prog . c rea teKerne l ( ”harlan_main_282” ) ;i n t dim_289 = str ide_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 , s t r ide_20 ) ;harlan_main_282_288 . setArg (3 , y_32 ) ;harlan_main_282_288 . setArg (4 , x_33 ) ;harlan_main_282_288 . setArg (5 , get_c l_buf fe r ( rk_143 ) ) ;harlan_main_282_288 . setArg (6 , get_c l_buf fe r ( rv_53 ) ) ;harlan_main_282_288 . setArg (7 , get_c l_buf fe r ( rv_63 ) ) ;g_queue . execute ( harlan_main_282_288 , dim_289 ) ;. . .i n t dot_48 = if_res_272 ;p r i n t ( dot_48 ) ;a s s e r t ( ( dot_48 ) == (20) ) ;. . .

Page 22: Slide

コンパイルしてみると

いくつか手を入れないとだめ

I オフラインコンパイルに対応

I $記号が使えないI ← 簡単なスクリプトで変換する程度

I _も好ましくないI ホストコードのDEVICE_TYPEの修正I clCreateProgramWithBinaryに対応

I あとは Altera OpenCLツールでコンパイルI aoc でハードウェア側を合成I ホストコードは arm-linux-gnuebahf-を使う

Page 23: Slide

動いた

Page 24: Slide

評価とか...

I 続きは後日 (Qiita? )

Page 25: Slide

まとめ

I 簡単な I/Oの追加をテスト → カメラの接続I “組み込み”にも嬉しいかもI 汎用の CPU/FPGA協調動作環境として

I メインメモリが簡単に使えるI ソフトウェア/CPUとの連携もI I/Oアクセス直結の処理は見通しよく書ける

I IOチャネルアクセスが一箇所は,ちょっと面倒I OpenCLでは書かないのが吉?I それ,Synthesijerで...?I 沢山チャネルはやして外でアービトレーション?

I より高級言語で Altera OpenCLを使うI できる (できた)I 記号の使い方に注意が必要I 最適化とかはこれから考えてみるI Irohaでよいのでは?

Page 26: Slide

ところで,Traxとかどうですか?http://trax-fit2016.github.io/contest/