FC2カウンター FPGAの部屋 新しいラプラシアンフィルタのソフトウェア実装

FPGAやCPLDの話題やFPGA用のツールの話題などです。 マニアックです。 日記も書きます。

FPGAの部屋

FPGAの部屋の有用と思われるコンテンツのまとめサイトを作りました。Xilinx ISEの初心者の方には、FPGAリテラシーおよびチュートリアルのページをお勧めいたします。

新しいラプラシアンフィルタのソフトウェア実装

OpenMPを使ったラプラシアンフィルタの動作がおかしいという現象があった。ブログのコメント欄でも教えてもらったのだが、OpenMPのプラグマを書いた for 文のどの順に実行されるかわからない?ということで、元のラプラシアンフィルタをよりシンプルにしてみた。
laplacian_filter.c ~ laplacian_filter4.c までは、ラプラシアンフィルタ処理によって、画像の周りの1ピクセルのみ 0 にしていたが、今回は上と右の 2 ピクセルを 0 にしている。下にその図を示す。ブルーの画面がラプラシアンフィルタの出力画像で、黒い部分が 0 を出力している部分とする。
OpenMP_23_150720.png

ラプラシアンフィルタは3 ピクセル x 3 ラインのデータを元に真ん中の画像を出力しているので、今回のソフトウェアの方が if 文が少なくなる。
実際のラプラシアンフィルタのソフトウェアはGitHubにあげておいたので、marsee101/laplacian_filters を見て欲しい。
laplacian_filter5.c は laplacian_filter.c に対応する実装で、順に番号付けされていて、 laplacian_filter8.c は、 laplacian_filter4.c に対応する実装となっている。

下に gcc-4.8 で laplacian_filter5.c の性能を比較した時のスクリプトを示す。

gcc laplacian_filter5.c -o laplacian_filter5
gcc -O1 laplacian_filter5.c -o laplacian_filter5_O1
gcc -O2 laplacian_filter5.c -o laplacian_filter5_O2
gcc -O3 laplacian_filter5.c -o laplacian_filter5_O3
gcc -Os laplacian_filter5.c -o laplacian_filter5_Os
gcc -mcpu=cortex-a9 -mfpu=neon -ftree-vectorize -mvectorize-with-neon-quad -ffast-math laplacian_filter5.c -o laplacian_filter5_n
gcc -mcpu=cortex-a9 -mfpu=neon -ftree-vectorize -mvectorize-with-neon-quad -ffast-math -O1 laplacian_filter5.c -o laplacian_filter5_n1
gcc -mcpu=cortex-a9 -mfpu=neon -ftree-vectorize -mvectorize-with-neon-quad -ffast-math -O2 laplacian_filter5.c -o laplacian_filter5_n2
gcc -mcpu=cortex-a9 -mfpu=neon -ftree-vectorize -mvectorize-with-neon-quad -ffast-math -O3 laplacian_filter5.c -o laplacian_filter5_n3
gcc -mcpu=cortex-a9 -mfpu=neon -ftree-vectorize -mvectorize-with-neon-quad -ffast-math -Os laplacian_filter5.c -o laplacian_filter5_ns
./laplacian_filter5
./laplacian_filter5_O1
./laplacian_filter5_O2
./laplacian_filter5_O3
./laplacian_filter5_Os
./laplacian_filter5_n
./laplacian_filter5_n1
./laplacian_filter5_n2
./laplacian_filter5_n3
./laplacian_filter5_ns
objdump -S -d laplacian_filter5 | grep "vmov" -c
objdump -S -d laplacian_filter5_O1 | grep "vmov" -c
objdump -S -d laplacian_filter5_O2 | grep "vmov" -c
objdump -S -d laplacian_filter5_O3 | grep "vmov" -c
objdump -S -d laplacian_filter5_Os | grep "vmov" -c
objdump -S -d laplacian_filter5_n | grep "vmov" -c
objdump -S -d laplacian_filter5_n1 | grep "vmov" -c
objdump -S -d laplacian_filter5_n2 | grep "vmov" -c
objdump -S -d laplacian_filter5_n3 | grep "vmov" -c
objdump -S -d laplacian_filter5_ns | grep "vmov" -c


laplacian_filter5.c を他のラプラシアンフィルタの実装に切り替えながら性能を測定した。

laplacian_filter5.c の結果を示す。
OpenMP_24_150720.png

laplacian_filter6.c の結果を示す。
OpenMP_25_150720.png

laplacian_filter7.c の結果を示す。
OpenMP_26_150720.png

laplacian_filter8.c の結果を示す。
OpenMP_27_150720.png

次に、OpenMP を使った時の各ラプラシアンフィルタ処理時間を測定した。
下に gcc-4.8 の -fopenmp オプションを付けた時の性能を比較するためのスクリプトを示す。

gcc -fopenmp laplacian_filter5.c -o laplacian_filter5_mp
gcc -fopenmp -O1 laplacian_filter5.c -o laplacian_filter5_mpO1
gcc -fopenmp -O2 laplacian_filter5.c -o laplacian_filter5_mpO2
gcc -fopenmp -O3 laplacian_filter5.c -o laplacian_filter5_mpO3
gcc -fopenmp -Os laplacian_filter5.c -o laplacian_filter5_mpOs
gcc -fopenmp -mcpu=cortex-a9 -mfpu=neon -ftree-vectorize -mvectorize-with-neon-quad -ffast-math laplacian_filter5.c -o laplacian_filter5_mpn
gcc -fopenmp -mcpu=cortex-a9 -mfpu=neon -ftree-vectorize -mvectorize-with-neon-quad -ffast-math -O1 laplacian_filter5.c -o laplacian_filter5_mpn1
gcc -fopenmp -mcpu=cortex-a9 -mfpu=neon -ftree-vectorize -mvectorize-with-neon-quad -ffast-math -O2 laplacian_filter5.c -o laplacian_filter5_mpn2
gcc -fopenmp -mcpu=cortex-a9 -mfpu=neon -ftree-vectorize -mvectorize-with-neon-quad -ffast-math -O3 laplacian_filter5.c -o laplacian_filter5_mpn3
gcc -fopenmp -mcpu=cortex-a9 -mfpu=neon -ftree-vectorize -mvectorize-with-neon-quad -ffast-math -Os laplacian_filter5.c -o laplacian_filter5_mpns
./laplacian_filter5_mp
./laplacian_filter5_mpO1
./laplacian_filter5_mpO2
./laplacian_filter5_mpO3
./laplacian_filter5_mpOs
./laplacian_filter5_mpn
./laplacian_filter5_mpn1
./laplacian_filter5_mpn2
./laplacian_filter5_mpn3
./laplacian_filter5_mpns
objdump -S -d laplacian_filter5_mp | grep "vmov" -c
objdump -S -d laplacian_filter5_mpO1 | grep "vmov" -c
objdump -S -d laplacian_filter5_mpO2 | grep "vmov" -c
objdump -S -d laplacian_filter5_mpO3 | grep "vmov" -c
objdump -S -d laplacian_filter5_mpOs | grep "vmov" -c
objdump -S -d laplacian_filter5_mpn | grep "vmov" -c
objdump -S -d laplacian_filter5_mpn1 | grep "vmov" -c
objdump -S -d laplacian_filter5_mpn2 | grep "vmov" -c
objdump -S -d laplacian_filter5_mpn3 | grep "vmov" -c
objdump -S -d laplacian_filter5_mpns | grep "vmov" -c


OpenMP を使った時の新しく作ったラプラシアンフィルタの性能を測定した。
laplacian_filter5.c に OpenMP用のプラグマを入れた。
OpenMP_32_150720.png

laplacian_filter5.c の結果を示す。
OpenMP_28_150720.png

laplacian_filter5.c のラプラシアンフィルタ結果を示す。今回は正常だ。
OpenMP_36_150720.jpg

laplacian_filter6.c に OpenMP用のプラグマを入れた。
OpenMP_33_150720.png

laplacian_filter6.c の結果を示す。
OpenMP_29_150720.png

laplacian_filter6.c のラプラシアンフィルタ結果を示す。今回は正常だ。
OpenMP_37_150720.jpg

laplacian_filter7.c に OpenMP用のプラグマを入れた。
OpenMP_34_150720.png

laplacian_filter7.c の結果を示す。
OpenMP_30_150720.png

laplacian_filter7.c のラプラシアンフィルタ結果を示す。今回は正常だ。
OpenMP_38_150720.jpg

laplacian_filter8.c に OpenMP用のプラグマを入れた。
OpenMP_35_150720.png

laplacian_filter8.c の結果を示す。
OpenMP_31_150720.png

laplacian_filter8.c のラプラシアンフィルタ結果を示す。今回も真ん中に線が入ってしまった。
OpenMP_39_150720.jpg

gcc-4.8 の各最適化オプションとNEON命令を追加した時、gcc-4.8 の OpenMPで 2 スレッドにした場合の性能を表にした。表中で同じ色の背景は出力位置は違っても同じ実装であることを示す。
最初にgcc-4.8 の各最適化オプションとNEON命令を追加した時の表を示す。
OpenMP_40_150720.png

gcc-4.8 の OpenMPで 2 スレッドにした場合の性能の表を示す。
OpenMP_41_150720.png

gcc-4.8 の OpenMP、-O3、laplacian_filter8.c で最速値 72.5 ms が計測できた。まだ、laplacian_filter8.c は結果がおかしいが最速値を計測することができた。一方、ラプラシアンフィルタの実行に関しては、1 core 使用した時と、2 core 使用した時では、あまり速度差が無いと言える。
  1. 2015年07月20日 07:56 |
  2. Zynq
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック URL
http://marsee101.blog19.fc2.com/tb.php/3203-c92ec231
この記事にトラックバックする(FC2ブログユーザー)