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