プログラマでありたい

おっさんになっても、プログラマでありつづけたい

CPUの気持ちになってプログラムを書くということ Kansai.pm#11 参加記その1

 この前の日曜日にKansai.pmに参加してきました。
Perlの人でもないし参加しても良いのかなぁと悩みましたが、HTML::ExtractContentを作った人の話が聞けるので行ってみました。正直、Hatenaを見たいのと生id:naoyaさんを見たかったというのもありますw


 一番最初の話が、吉田さんによるプログラムの高速化の話。いきなりレベルの高い話で、周りの人も頭良さそうな人ばかりだったので、参加する所間違えたかなぁと一人内心焦っていました。
Cell Challenge 2009 参加記


 高速化の観点は、以下の3点

  • アルゴリズムの高速化
    • ビット並列化
  • CPU(正確には、SPE)一つ単位での高速化
    • パイプライン
    • データ依存とデータハザード
    • ループアンドローリング ループアンローリング (訂正 2009/03/28 14:30)
  • 複数CPUで分散処理をさせる時の高速化


 どれも難しい内容を、解り易く説明して頂いたので大変勉強になりました。どの話も為になる話だったのですが、特に衝撃を受けたのがCPU一つ単位での高速化の話です。最初に1命令を複数工程に分割し、ずらしながら実行するパイプライン処理の説明がありました。次に、工程の依存関係によりスループットが落ちる例(データハザード)を図解して頂きました。ここまでだったら、情報処理試験を受けたことがある人間ならば、誰でも知っている内容です。しかし、その後に具体的にどういうコーディングであれば、データハザードを回避出来るのかという例を示してくれました。ここで私は衝撃を受けました。CPUの処理を考えてコーディングしたことがないなと。知識として持っているコンピュータの動きというのを知識のままで終わらせているということに気が付かされました。
 実際のところ、アプリを作る場合はファイルアクセスやDBアクセスの辺りに特に注意を払っていれば、パフォーマンスの問題が発生することはほとんど無いです。それでも、普段からアーキテクチャーを考えてコーディングすることは大事だなと思いました。(後輩には、よくDBの気持ちになってSQLを書けと言ったりしてるんですがねw恥ずかしい限りです。)


 ちなみに、下記のコードはデータハザードを解消する為のコーディング例です。データハザードは、命令が利用するデータ間に依存関係がある場合に発生します。前の命令が終わらないと後ろの命令が実行できないとか。ですので、それを解きほぐしてやれば、並列で処理が出来るようになります。

追記 2009/03/28 14:30
下記の例はLoopの評価が無い為に高速になっているだけで、ループアンローリングとは関係のない話でした。申し訳ございません。
色々な方にコメントやトラックバック、はてブで指摘して頂きました。ありがとうございます。

#!/usr/bin/perl

use strict;
use warnings;
use Time::HiRes qw ( time );

my $sum;
my $start;
my $end;
my $max = 10000000;

$sum = 0;
$start = time();
for (my $i=0; $i<$max; $i++) {
  for (my $j=0; $j<3; $j++) {
   $sum = $sum+($i+$j);
  }
}
$end = time();
print $sum,"\n";
printf("%.4f secs\n", $end - $start);

$sum = 0;
$start = time();
for (my $i=0; $i<$max; $i++) {
  $sum = $sum+($i+0);
  $sum = $sum+($i+1);
  $sum = $sum+($i+2);
}
$end = time();
print $sum,"\n";
printf("%.4f secs\n", $end - $start);
$ ./test.pl 
150000015000000
9.0000 secs
150000015000000
6.0000 secs

 1.5倍になりました。目で見てみると面白いです。 高速化は、for文の評価が必要ない為です。ループアンローリングとは無関係でした。
まぁ速度をとるか、保守性をとるかと言えば、ほとんどの場合は保守性でしょう。しかし、ちゃんと押さえておきたいですね。


Kansai.pmネタは整理してまだまだ書きたいので、不定期で続けます。