ハードウェアがソフトウェアよりも遅くなる瞬間
「専用ハードウェアは同じ計算をするソフトウェアよりも必ず早い」
普通そうだと思いませんか?私も先日まで思っていました。結論を言うと、早いのは間違いないのですが、「設計を誤るとハードウェアを使うと逆に遅くなる例がある」ということです。今日はそのことを皆さんにぜひお伝えしたいです。
最近SDSoCの話をした
このブログより2つ遡ったブログで、SDSoCについてお話しました。
SDSoCというのは、FPGAで有名なあのXilinxが配布しているIDEのことです。何ができるかというと、Xilinx社が発売しているFPGA評価ボードを扱うためのものです。
具体的に言うと、C言語でソースを書いてそのコードをHW/SW協調設計にてFPGAで高速化できる!といった素晴らしい代物です。私の研究の一環でこれを使って、SSIM計算なるものを高速化しようと企てていたときのことでした。
計算をハードウェア化したはずなのに逆に遅くなっている
C言語で件のソースを書き、SDSoCの機能を使いワンクリックでハードウェア化して、予め用意したソフトウェア関数と一緒に実行してどちらが早いか確認しました。
実行にかなり時間がかかったので、「おやおや?ソフトウェアは随分と実行が遅いですね????」と心のなかで煽りながら結果を楽しみに待っていました。
10分後結果が出たので、ニヤニヤしながら画面に映る実行結果を見て顔が青ざめました
「ソフトウェア計算速度の1/250ってなんやねん!」
そう、とてつもなくハードウェアが遅かったのである。流石におかしいと思い、少し解析してみた結果次のようなことがわかりました。
- SSIM計算は2乗計算が頻繁に呼ばれる
- 引数はソフトウェア側から一つづつハードウェア関数に投げられる
そしてある一つの仮定を経てました
「 2乗の計算ってソフトウェアのほうが早い???? 」
何事も実験なしには結論を出してはいけないので
プロジェクトを新しく作り実験をして確かめました。ソースはだいたい下のものです。
ーーーーーーーSQUARE.cppーーーーーーー
float SQUARE(float x){
return pow(x, 2);
}
void array_square(float *A, float *B){
for (i = 0; i < N; i++)
B[i] = SQUARE(A[i]);
}
ーーーーーーーSQUARE.cppーーーーーーー
SDSoCからソース上部の方のSQUAREだけをハードウェア化して実行しました。結果から言えば、激遅でした。ソフトウェアの1/120も遅かったです。
遅いと分かったでけでは納得行かなかったので、どうにかもう少しマシにならないか考えました。そしてある疑惑が生まれました
疑惑を払拭するためにまたプロジェクトを立てた
新しいプロジェクトでは先程のソースコードを若干修正して次のようになりました。
ーーーーーーーSQUARE.cppーーーーーーー
float SQUARE(float x){
return pow(x, 2);
}
void array_square(float *A, float *B){
float *C = *A;
for (i = 0; i < N; i++)
C[i] = SQUARE(C[i]);
*B = *C;
}
ーーーーーーーSQUARE.cppーーーーーーー
前回から何が変わったかというと、関数の中に一時変数を用意してそちらで計算するようになりました。そして、SQUARE関数だけでなくarray_square関数もハードウェア化しました。そして結果は…
う〜ん、ソフトウェアより0.7倍!w
まだまだ遅いですが、1/250よりもまともな数字になりました。実質85倍速です。
実験結果からの考察
先の実験結果から、次のことが言えそうです。
- 通信オーバーヘッドは計算速度より遅くじゃまになる
- 一時変数にコピーするとある程度ましになる
- 計算速度>>通信オーバーヘッドの場合、高速化の兆しがある
私の人生はHW/SW協調設計をしたことがなく、だいたいソフトウェアだけかハードウェアだけの計算でした。ですが今回始めて協調設計に踏み出したところ、まさかの「通信時間によるオーバーヘッド」の存在を意識させられました。
きっとこれからはHW/SW協調設計の時代が来るかと思いますが、通信オーバーヘッドなど強調設計するとき特有の問題を意識しながら、システムを設計できる力を身に着けたいですね。