TBitmapでマルチコア分散処理するときの注意点
NHKで赤い…。
それはともかく、ホームページをごにょごにょと整理したついでに、バグってる公開済みコードも直そうとマルチコアのソースを修正しておりました際に見つけた、かなりドハマリなお話です。
以前(XP)なら特に問題もなかったのですが、環境が変わったためか、分散するだけ重くなると言う現象が発生しました。
分散するだけ重くなる・・・フフフ素敵ですね。
色々やった結果、結局のところ、TBitmap.Scanline[]がマルチコア分散処理に使えないという事が分かりました。
なんだか以前は大丈夫だった気がするんですが、過去を振り返っても仕方ありません。
procedure __MultiCoreFunction(dptr:pointer); begin for dest := TBitmap(dptr).Scanline[y]; //call GetScanline end end;
こんな感じだと、アウトです。
回避するには、ScanlineのPointerを変数配列に待避させて、それを渡せば解決です。
type THogeRecord=recrd scanline : array of pointer; end; PHogeRecord=^THogeRecord; procedure __MultiCoreFunction(dptr:pointer); begin for dest := PHogeRecord(dptr)^.Scanline[y]; end; end; //前処理:scanline pointerの取得 procedure main; var h,i : Integer; r : THogeRecord; begin h = bmp.height; SetLength(r.Scanline,h); for i:=0 to h-1 do r.scanline[i] := bmp.Scanline[i]; end; 〜〜 end;
構造体なりクラス宣言する必要があるので、ちょっと面倒ですね。
今まで全然気づかなかったのは、自前画像ライブラリだと高速化するためにLoadやSetSize時にScanlineを配列に待避してそれを使っているので、知らないうちに回避されてたためで、いやはや怖いですね。
TBitmap.scanlineのどこが悪いかまでは探ってませんが(探る気も無いですが)、DIBNeedとかあのへんが怪しい気がします。
とはいえ、上記で簡単に回避できるので、原因を深くは考えないようにしたいと思います:-Q