ページ 11

画像処理プログラムと、処理速度について。

Posted: 2012年12月09日(日) 14:22
by いちこ
こんにちは。
本日もよろしくおねがいします。

今、1600*1600画素のRAW画像を読み込み、補正を行って書き出すプログラムを作成しています。
画像を読み込む配列の宣言、読み込み、処理、書き出しの速度の合計を測定しているのですが、疑問に思うことがあります。


1画素ずつ読み込んで、書き出す方式は、とても処理速度が遅かったので…
1600*1600画素の画像を、1600*1600個要素を持つ配列に、1枚いっきに読み込む方法の方が
1600画素を、1600個要素を持つ配列に、1600回読み込む方法よりも、処理速度が速いと予想していたのですが

gettimeofday関数を用いて、速度の測定を行ったところ、
前者は10回実行した平均が 16980マイクロ秒
後者は10回実行した平均は 15532マイクロ秒
となりました。
ほとんど差はありませんが、少し、1600回に分けて読み込んだ方が速いです。

これが、なぜだかわかりません。
なぜ
1600回<1回<1600*1600回 (読み込み)
となってしまうのでしょうか。

また、下のプログラムでは、buf,buf2をstaticの領域に確保していますが、
staticをはずして、stack領域に確保したところ、少しだけ速度が落ちてしまいました。
これも、stackのほうが速いと思っていたので、予想外の結果でした。

曖昧な質問で申し訳ありませんが、どなたか詳しい方がおられましたら、ご教示お願い致します。

下にソースコードを記します。
(コード全体は長いので、速度を測っている部分以外は割愛します。見たい部分がありましたらご指摘ください)

1600画素を1600回読み込み

コード:

  time_a=get_dtime();

  static unsigned char buf[1600];
  static unsigned char buf2[1600];


  for(i=0; i<1600; i++){ 
     fread(buf,1,1600,fp);
    
     for(j=0; j<1600; j++) buf2[j]=table[buf[j]];
    
    fwrite(buf2,1,1600,fp_adjusted);
  }

  
 time_b=get_dtime();

1600*1600画素を1回読み込み

コード:

  time_a=get_dtime();

  static unsigned char buf[1600*1600];
  static unsigned char buf2[1600*1600];


  fread(buf,1,1600*1600,fp);

  for(i=0; i<1600*1600; i++)  buf2[i]=table[buf[i]];

  fwrite(buf2,1,1600*1600,fp_adjusted);
  
  time_b=get_dtime();

Re: 画像処理プログラムと、処理速度について。

Posted: 2012年12月09日(日) 14:40
by softya(ソフト屋)
ここらへんはOSやらCPUのアーキテクチャやらCPUキャッシュの性能で決まりますので、PCが変わる毎に計測結果が変わる可能性があります。
※ x86系CPUはCori7やら色々ありますが同じx86でもクロック以外に中身違うバージョンが色々とありますので多少の差では優位な方のが同じという計測結果は期待できません。

それとWindowsの場合は他プロセスの影響を受けますので、数十ms単位の誤差は当然のように生まれます。たぶん、何時間も測定しないと正しい結果は得られないです。

ちゃんと計測したいなら、
1.他のプロセスを出来るだけ止めること。
2.ネットも切断すること。
3.ウィルス対策ソフトも一時的に停止。
4.PCに触らす何時間も計測すること。
5.必ずリリースビルドすること。
あたりは最低限やってみてください。
ぜんぜん違う結果になる可能性があります。

【訂正】
gettimeofdayはLinuxですかね?
Linuxでも他のプロセスの影響を受けるので同じ事が言えます。

あとgettimeofdayの精度についても調べてみてください。
信頼度を調べるために標準偏差も取ってみたほうが良いでしょう。 ばらつきが大きいとあまり信用できません。

Re: 画像処理プログラムと、処理速度について。

Posted: 2012年12月09日(日) 14:52
by いちこ
>>softyaさん
返信ありがとうございます。
なるほどです。
今使っているのはUnixなのですが、1ミリ秒くらいの差は、いつもあるとは考えないほうがよさそうですね。
ということは、今、できるだけ速いプログラムを作りたいと思っているのですが
この処理の場合、どちらの方法で読み込んでも、メモリの領域がstackでもstaticでも大差ないということ、ですよね(><;)

ただ、一般にはstaticよりもstackのほうが、アクセス速度は速いということでいいのでしょうか。

Re: 画像処理プログラムと、処理速度について。

Posted: 2012年12月09日(日) 14:55
by softya(ソフト屋)
>ただ、一般にはstaticよりもstackのほうが、アクセス速度は速いということでいいのでしょうか。

変わらないはずですが、アクセス頻度によりCPUのデータキャッシュの動作が変わっている可能性があります。
特定のCPUだけの個性かもしれませんので、何とも言えません。

【補足】
上にも書きましたが標準偏差も調べて見ることをオススメします。

Re: 画像処理プログラムと、処理速度について。

Posted: 2012年12月09日(日) 15:07
by いちこ
>>softyaさん
返信ありがとうございます。
そうなんですか!
てっきりstackのほうが速いものなのだと思い込んでおりました。気をつけます。

2つ前の返信も、詳しくしてくださってありがとうございます。
gettimeofdayはマイクロ秒の精度ですが、プログラムを実行して速度を測ったときのばらつきは大きかったです。
やはり、結果が欲しいなら厳密にしなければいけませんね。
標準偏差もとってみようと思います。

Re: 画像処理プログラムと、処理速度について。

Posted: 2012年12月09日(日) 15:20
by いちこ
これでこのトピックは解決済みとさせていただきます。
softyaさん、ありがとうございました。

Re: 画像処理プログラムと、処理速度について。

Posted: 2012年12月09日(日) 15:20
by softya(ソフト屋)
何処でも通用する高速化の方法として思いつくのは

・出来るだけOSに近い低水準な関数を使う。
・非同期で最適な頻度でファイルアクセスを行う。
・コンパイル・リンク時の最適化をスピード優先で最適化する。
・メモリに出来るだけランダムアクセスが発生しないように連続なアクセスを心がける。
・CPUキャッシュに収まる用に出来るだけデータバッファはコンパクト化する。
・バイトアクセスよりも4バイト単位のメモリアクセスを行う。
・コンパイラの出すアセンブラコードを眺めて無駄がないか検討する。

あたりででしょうか。

Re: 画像処理プログラムと、処理速度について。

Posted: 2012年12月09日(日) 16:16
by いちこ
>>softyaさん
返信ありがとうございます。

たくさんのアドバイスをありがとうございます!
参考にさせていただきます…!
またわからないことがあったとき、よろしくおねがいします。