2024/02/07(水) [n年前の日記]
#1 [basic] FreeBASICで反転描画。その3
Windows10 x64 22H2 + FreeBASIC 1.10.1 32bit で、標準機能のグラフィック描画で反転描画する方法について調べてる。
_昨日 、 _imgput() を改造して、透明色を有効にする版にしてみたけれど、もう少し高速化できないものかと思えてきた。
試しに、おそらくは横一列を描画するループの中で、ポインタに += n をしていたあたりを += 1 になるように修正してみたのだけど…。Put() に比べて5倍遅かったのが、4倍ちょっとぐらいにはなった。
ただ、元画像を参照するポインタも += 1, -= 1 にしてみたところ、90度、270度回転の結果がグチャグチャになってしまった。そこは変更できないようだな…。書き込む側は横方向/右側に進んでいくけれど、参照する側は左右だけではなく縦方向に進んでいく場合もあるのだろう…。
回転処理は諦めて、水平垂直反転のみサポートということにすれば、もう少し高速化できたりするのだろうか。いや、焼け石に水かな…。
_昨日 、 _imgput() を改造して、透明色を有効にする版にしてみたけれど、もう少し高速化できないものかと思えてきた。
試しに、おそらくは横一列を描画するループの中で、ポインタに += n をしていたあたりを += 1 になるように修正してみたのだけど…。Put() に比べて5倍遅かったのが、4倍ちょっとぐらいにはなった。
ただ、元画像を参照するポインタも += 1, -= 1 にしてみたところ、90度、270度回転の結果がグチャグチャになってしまった。そこは変更できないようだな…。書き込む側は横方向/右側に進んでいくけれど、参照する側は左右だけではなく縦方向に進んでいく場合もあるのだろう…。
回転処理は諦めて、水平垂直反転のみサポートということにすれば、もう少し高速化できたりするのだろうか。いや、焼け石に水かな…。
◎ ソース :
現状のソースは以下。
_imgputt_new.bi
_putex.bi
_imgputt_test.bas
_imgputt_test2.bas
使用画像は以下。
_sprite_8bit.bmp
_sprite_16bit.bmp
_sprite_24bit.bmp
以下でコンパイルできる。
実行は以下。コマンドラインオプションで、8, 16, 32 のどれかを指定すれば、ウインドウを 8bit, 16bit, 32bitモードで作るようにしてみた。
imgputt_test.exe, imgputt_test2.exe の実行結果は以下。
_imgputt_new.bi
_putex.bi
_imgputt_test.bas
_imgputt_test2.bas
使用画像は以下。
_sprite_8bit.bmp
_sprite_16bit.bmp
_sprite_24bit.bmp
以下でコンパイルできる。
fbc imgputt_test.bas fbc imgputt_test2.bas
実行は以下。コマンドラインオプションで、8, 16, 32 のどれかを指定すれば、ウインドウを 8bit, 16bit, 32bitモードで作るようにしてみた。
imgputt_test.exe 32 imgputt_test2.exe 32 imgputt_test.exe 8 imgputt_test2.exe 8 imgputt_test.exe 16 imgputt_test2.exe 16
imgputt_test.exe, imgputt_test2.exe の実行結果は以下。
◎ gccを使ったら速くなった :
ふと、gcc の最適化を指定したらどうなるかなと思いついた。通常、FreeBASIC 32bit版は、gas (as.exe, GNUアセンブラ)を利用してコンパイルしてるらしいけど…。
MinGW (gcc 6.3.0) を使える状態にして、FreeBASIC のソースのコンパイルに gcc を使いつつ、かつ、最適化をかけるように指定して exe を生成してみた。
_コンパイラ・オプション: -gen - CompilerOptgen
_コンパイラ・オプション: -O - CompilerOptoptimization
何と言うことでしょう。ソースは前と変わってないのに、gcc でコンパイルさせただけで、4倍ちょっとの遅さが、1.8倍程度の遅さになった。いやはや、gcc の最適化処理は優秀なんだなあ…。
しかしこうなると、高速化できないかとチマチマ修正してコンパイルして動作確認するのも馬鹿馬鹿しいというか…。まずは gcc でコンパイルしようぜ、話はそれからだ。みたいな。もっとも、高速化したいならまずはアルゴリズムをどうにかできないか考えるのが先だろうけど。
その後も試していたら、-O 3 をつけると 1.8倍だったのが、-O 2 にすると 1.5倍になった。必ずしも -O 3 のほうが良いというわけではないらしい。
MinGW (gcc 6.3.0) を使える状態にして、FreeBASIC のソースのコンパイルに gcc を使いつつ、かつ、最適化をかけるように指定して exe を生成してみた。
fbc imgputt_test2.bas -gen gcc -O 3
- -gen gcc ... gcc を使って exe を生成
- -O 3 ... 最適化レベル 3 を指定。
_コンパイラ・オプション: -gen - CompilerOptgen
_コンパイラ・オプション: -O - CompilerOptoptimization
何と言うことでしょう。ソースは前と変わってないのに、gcc でコンパイルさせただけで、4倍ちょっとの遅さが、1.8倍程度の遅さになった。いやはや、gcc の最適化処理は優秀なんだなあ…。
しかしこうなると、高速化できないかとチマチマ修正してコンパイルして動作確認するのも馬鹿馬鹿しいというか…。まずは gcc でコンパイルしようぜ、話はそれからだ。みたいな。もっとも、高速化したいならまずはアルゴリズムをどうにかできないか考えるのが先だろうけど。
その後も試していたら、-O 3 をつけると 1.8倍だったのが、-O 2 にすると 1.5倍になった。必ずしも -O 3 のほうが良いというわけではないらしい。
◎ 8bitモードや16bitモードは遅い :
今までウインドウの色深度について32bitモードで動作確認していたけれど、8bitモードや16bitモードにして動作確認したら、同じような処理をしているのに処理時間が10倍以上に増えてしまった。扱うデータのバイト数は1/4、1/2になっているはずなのに、どうしてそんなことになるのだろう…。
もしかして、バイト単位で処理をする時は、4バイト読み込んで、そのうち1バイトを取り出して、みたいな処理になってしまうのだろうか…? 4バイト単位で処理したほうがシンプルになって、処理時間は速くなる?
もしかして、バイト単位で処理をする時は、4バイト読み込んで、そのうち1バイトを取り出して、みたいな処理になってしまうのだろうか…? 4バイト単位で処理したほうがシンプルになって、処理時間は速くなる?
◎ MMX機能の有無で使うルーチンが違うのかもしれない :
FreeBASIC の Put() 関連ソースを眺めてたら、CPUがMMX機能を持ってる場合、アセンブラで書いたルーチンを利用してるように見えた。
_fbc/src/gfxlib2/x86/gfx_put_trans_mmx.s at master - freebasic/fbc
だから Put() は速いのかな…。だとしたら、アセンブラで書かないと Put() の速度に近づけないのかもしれない…。
_fbc/src/gfxlib2/x86/gfx_put_trans_mmx.s at master - freebasic/fbc
だから Put() は速いのかな…。だとしたら、アセンブラで書かないと Put() の速度に近づけないのかもしれない…。
[ ツッコむ ]
以上です。