あざらしなので

備忘録と日常のこと

Raspberry Pi4のGPGPUに挑戦(その1)

””””内蔵GPUもったいなくないですか?””””

Raspberry Pi4には計算資源としてCPUの他にVideoCoreⅥ(VC6)と呼ばれるGPUが搭載されています。

GPUを汎用計算に活用するGPGPUは一般的にNvidia社の外付けGPUを用いて行われていますが、組み込みボードやノートPCでもGPUは搭載されているものがあり、GPGPUが可能です。(技術的には)

組み込みボードでは計算資源の拡張が難しいのでGPGPU活用は色々と嬉しいことがあると思います。

今回は組み込みボードの代表格であるRaspberry Piの最新機、Pi4でGPGPUに挑戦します。

VC6-GPGPU プログラミング方法

Python上でVideoCore6のアセンブリを記述&実行できる神ライブラリpy-videocore6がIdein社から公開されています。

github.com

アセンブラなのでプログラミングにはVC6のハードウェア構造を理解する必要がありますが、一般にアーキテクチャリファレンスは公開されていません。また、上記ライブラリ自体のドキュメントも存在せず知識0からの開発はかなり難易度が高いです。

ですが、一応ネット上に公開されている情報からできなくはないです。

1)VC6アーキテクチャはVC4と類似

Raspberry Pi zero,1,2,3に搭載されているVideoCoreⅣ(VC4) GPU完全なアーキテクチャリファレンスが公開されています。

https://docs.broadcom.com/doc/12358545

py-videocore6のVC4版も公開されており(こちらが先)、サンプルのSGEMMを解説したQiita記事も存在します。

github.com

qiita.com

(有料ですが過去に私が執筆した入門書もあります。)

booth.pm

上記をすべて網羅すればVideoCore4のGPGPUができますね。VC4からVC6へのキャッチアップには↓の記事が良いと思います。(リファレンスなしでGPGPUはヤバすぎる....)

Idein Ideas — GPGPUの観点から見る VideoCore VI と VideoCore IV の違い

2)サンプルコードが豊富

実際のプログラミングにはpy-videocore6リポジトリのexamplesフォルダのコードを読めば雰囲気がつかめると思います。testsフォルダにて各機能を試すことができるのでexamplesを読みつつ命令の挙動確認にtestsコードを使うのが良いと思います。

VC4のSGEMMにあったような細かいレジスタ節約のテクニックは同社のQMKL6のsgemmあたりを読めば大体わかります。

github.com

VideoCore6アーキテクチャ

↑の記事にすべて書いてありますが概要だけ一応

VC6はQPUと呼ばれる4way-SIMD演算器が8個搭載されています。命令では各QPUが4cycle使って16way-SIMDとして動作します。FMAがあり、500MHzで駆動するのでFLOPSは

4(QPU) x 8 x 2(FMA) x 0.5 =32GFLOPS

となります。Pi4のCPUは48GFLOPSらしいので""GPGPUで高速化!!""には期待できず、GPUオフロードによるCPUの負荷軽減やCPU-GPU並列計算での高速化とかに使えると思います。

レジスタSIMD計算機なので長さ16のベクトルレジスタとなっています。各QPUにはアキュムレータ5本(r0~r4)と64本(rf0~rf63)のレジスタファイル、1個のスカラ用レジスタ(r5)があります。

レジスタが多く、SIMTではなくSIMDアーキテクチャなので昨今のGPUというよりはベクトル計算機に近いような気がします。(GPUベクトル計算機の明確な違いを良くわかっていない)

次回はVC6でSGEMMを実装します。すでにpy-videocoreのサンプルやQMKL6にて実装されたものが公開されていますが、あえてこれらは深く読まず、自分で考えて書いてみます。実装できたらFLOPSバトルして実装法の差分から考察できれば勉強として楽しそう。

最終的にはCPUのOpenBLAS SGEMMとGPUのSGEMMを使ったCPU-GPU並列動作でどれくらいの性能が出るのか実験したいと思います。SoCのCPUとGPUはメモリが共有なので同時利用による帯域の圧迫や消費電力制限によるクロック制限などで満足に性能は出ないような気がしていますが、面白そうなのでやってみます。

2020年振り返り

時間が過ぎるのが早いと思っていたらもう5月が終わり6月が終わり7月が....もう2020年も終わりますね. 今年は学部を卒業し同大学の修士に入学した年でしたが卒業式も入学式もコロナの影響でなくなり,気づいたらM1年生ももうすぐ終わるという時期まで来てしまいました.あっという間だった1年,数年後には空白期間扱いになっていそうなので振り返りを書きます.

1~3月

今年始まってすぐは岩手に帰ってきたぞーって気分でした.というのも去年,夏のインターンで1か月東京のとある会社で働いていたのが楽しくて,大学にいるよりここで働いていたほうが勉強になるのでは(大学でやっているものと同じ分野の研究開発業務だった)と考え,講義もゼミ以外なかったこともあり,全方向に駄々をこねて2019年いっぱいは東京勤務をしていました.私のボスは学生の活動について理解がある方だったので卒論の進捗はちゃんと出すことと毎週オンライン(ビデオ通話)でゼミに参加することを条件に承諾してくださり,卒論もB3でほとんどやっていたので作業量も少なく楽しい東京生活を過ごしていました.ちなみにお仕事は現在も同社でリモートアルバイトとして継続しています. 初っ端から去年の振り返りになってしまいましたが,岩手に帰ってきた後はゆるーく卒論を書きながら最後の学部生生活を過ごしていました.(特に面白い記憶がない)

4~7月

大学院に入学し,学部時代の友人知人はほとんどが就職して岩手から脱出しました.知り合いが少ないこと,コロナによるオンライン授業化もあり日常的に会話する回数が激減したのはしんどかったなーと思います.一人の時間が多かったせいもあってか,自分はなぜ何のために大学院に進学したのか,やりたいこととは好きなこととは....と色々考えてしまい動けなくなった時期でもありました.今はモチベーションは回復して動けていますが,当時はあまり意味のないことを考えて消耗していたなーと思います.目の前にあるものをただこなすということは時にメンタル面において重要ですね.漠然とあるタスクや将来の不安を俯瞰してしまうと辛くなるということを知りました.

8~10月

記憶がない.私は年2回夏と年末に実家に帰り,親にあれあれやってたよーとか生存報告をするのですが,この時帰ったときは何も変わってないとしか言ってない記憶があります.というか今までがインパクトあるイベントが多く話題が何かと尽きない状況だったのかもしれません.本当に何も覚えていない...講義の課題がしんどかった気がする.研究がポシャって萎えたのは覚えている...

11~12月

研究会の原稿書きました.毎回締め切りぎりぎりでの執筆となりボロボロで書き上げて,提出の数日後読み返して駄文過ぎてすべてを消し去りたくなる現象があります.反省して次はきれいに書きたい(素振り).今回の研究はアルバイトでやっていたものを学会発表しました.お給料をもらい,自分が好きな研究をして,勉強になり,その知見を学会発表できるというのは,今自分はとても良い環境にいるなぁと思います.(だからこそもっと頑張りたいと思う).また,私のアルバイト先と弊研究室で共同研究も始まる予定です.インターン,アルバイト,共同研究と色々お世話になりっぱなしで社には足向けて寝られませんね本当..(本当にありがとうございます)

まとめ

去年や一昨年はインパクトあることをやっていたためか今年はかなり地味な印象です.必要な勉強はやっていたので能力は着実に向上しているかなと思います.ただ,やっていることが高速化とか並列化とかHPCな話が多くそれ以外もやってみたいなーと思っていたら1年が終わりました.積読消化したい... 2020年は色々と準備期間だったと割り切って来年は怒涛の1年にしたいと思っています.あざらし頑張ります.

Winograd_k7x7_st2勉強メモ

Winograd_st2勉強メモの続き.今回はカーネル7x7の実装法についてメモする.

カーネル7x7でも3x3と同じように入力ブロックをいくつかのグループに分けて畳み込み計算をする(元論文参照).計算量を削減するために各グループの畳み込みはWinogradで計算する必要があり,3x3では以下のツールで必要な変換行列を求めることができた.

github.com

このツールでは入力にpolynomial interpolation pointsとブロックの出力サイズ,カーネルサイズを与えると計算に必要な変換行列を返してくれる.WinogradはF(N,M)とF(NxN,MxM)は同じ変換行列を使い,計算方法が異なる.そのため上記のツールでは入力がNとMだけで,F(2x2,3x3)やF(4x4,6x6)などの変換行列を知ることが出来た.しかし,7x7_st2にはWinograd F(2x2,4x3)があり,一筋縄ではいかない(そもそもWinograd Convolutionを理解すれば良い話であるが...).

試行錯誤の結果,以下の変換行列でF(2x2,4x3)が計算できることが分かった.(追記:論文に4x3の変換行列について書いてありました...見落としてた)

 G=\begin{pmatrix}
  0.5&   0&   0&   0\\
 -0.5&-0.5&-0.5&-0.5\\
-1/6&1/6&-1/6&1/6\\
1/6&1/3&2/3&4/3  \\
0&0&0&1
\end{pmatrix}
 KG=\begin{pmatrix}
  1&   0.5&   0.5&   0\\
 0&0.5&-0.5&0\\
0&0.5&0.5&1
\end{pmatrix}
 B=\begin{pmatrix}
2&-1&-2&1&0\\
0&-2&-1&1&0\\
0&2&-3&1&0 \\
0&-1&0&1&0 \\
0&2&-1&-2&1
\end{pmatrix}
 KB=\begin{pmatrix}
1&0&0&0\\
0&1&-1&-1\\
-1&1&1&0 \\
0&0&0&1 \\
\end{pmatrix}
 A=\begin{pmatrix}
1&1&1&1&0\\
0&1&-1&2&1
\end{pmatrix}
 KA=\begin{pmatrix}
1&0\\
1&1\\
1&-1\\
0&1
\end{pmatrix}

計算式は以下

Y=A[[ GgKG]⊙[BdKB]]KA

GPGPU実装をするにあたって自分用にリファレンス実装をnumpyで書いた.

github.com

Winograd stride2勉強メモ

Winograd Stride2の実装法ないかなーってググったら新しめの論文が出てきたので読んでメモ
Stride 2 1-D, 2-D, and 3-D Winograd for Convolutional Neural Networks
この論文の提案手法ではNvidiaGPUにて通常の畳み込みよりカーネル3x3で1.44倍,5x5で2.04倍,7x7で2.42倍,3x3x3で1.73倍速くなっているようです.
このメモでは3x3のみ解説していきます
Winograd自体の解説はこちら

続きを読む

Winograd勉強メモ

忘れるからメモ

Winogradとは

畳み込み演算を高速に計算できる(かもしれない)アルゴリズム

論文↓
Fast Algorithms for Convolutional Neural Networks

Winograd F(2x2,3x3)

入力画像を4x4,出力画像を2x2,カーネルサイズを3x3のwinogradアルゴリズム
計算式は以下の通り

Y=A^ T[[ GgG^ T ]⊙[B^ TdB]]A

続きを読む