フリーソフトの小道   

コンピュータ・プログラマー養成講座(入門編)

第4回 アルゴリズムの改良とは
〜処理のスピードアップをどのようにして実現するか〜

プログラミングでは「正確」、「速い」、「使いやすい」を基本に考える

 プログラミングの上で考えなければいけないこととは、第一に「処理を正確に間違いなく終えること」、 第二に「短い時間で処理を終えること」、第三に「使いやすく出来ていること」に尽きる。 短い時間で処理を終えるとは、がんばって仕事をすればよいというものではない。 コンピュータは人間と違ってサボらないから、指示通り最大のスピードで仕事をこなすように出来ている。 処理スピードを速くするとは、「無駄な仕事を省いて、全体の仕事の総量を減少させるように、 コンピュータに指示することで実現できる。 手を抜いて仕事を少なくするのでは、第一の目的「正確さ」に支障がでる。 スピードアップは無駄な処理を行っている部分がどこにあるか、それを見つ出すことから始まる。

「速い」を実現するには「仕事の総量を少なくすること」

 プログラムがする仕事の総量を少なくするとは、 プログラムの中で無駄な仕事をしている部分をどのようにして見つけるかにかかっている。 見つけることができれば、それを省いて仕事をする「手順(アルゴリズム)」をプログラムに記述するだけになる。 この処理の手順(アルゴリズム)の改善がプログラムのスピードアップの全てになる。 具体的な事例を挙げて説明することにしよう。

 プログラミング・コンテストの「素数発見」のプログラムにそれを見つけてみよう。 原型のアルゴリズム(このシリーズの第3回で示されている)をもう一度ここに示してみよう。

  1. 打ち切りする上限値を入力する。
  2. 打ち切り数が10,000 を超えておれば10,000とする。
  3. スタートする数 J を 2 とする。
  4. 数 J を「素数判定」する。
  5. 素数であれば、素数として表示する。
  6. 数 J を1増やす。
  7. 数 J が上限値未満でれば、処理番号 4 に戻り、処理を継続する。
  8. 数 J が上限値以上であれば、終了する。

 このアルゴリズムに無駄な部分がたくさん含まれている(だから、素数発見に時間がかかっている)。 処理1,2,3 については改善の余地はない。繰り返しで行われる部分に無駄があれば無駄も繰り返される。 無駄な部分を見つけるコツは繰り返し部分に注意して探せばよい。 繰り返し処理の処理4 からの素数判定の部分に改善の余地を探してみよう。

改善@ 素数判定は奇数のみでよい(2以外の偶数は素数ではない!)

 2から始める素数判定処理に無駄はないだろうか。素数判定は 1 ずつ増やして判定を繰り返している部分のことだ。 具体的に数値を入れて確かめて見ればよい。最初に 2 を確かめ、次に 3 を確かめ、次に 4 を確かめ、次に 5 を確かめ、次に 6 を確かめ.... と 考えてゆくと誰でもすぐに気付くだろう。
「偶数は確かめる必要がない! 明らかに2で割り切れるのだから!」
 したがって、この素数判定部分の繰り返しでは、奇数だけ確かめるように手順を変えるようにすることだ。 たったこれだけの手順変更だけで、素数判定処理が半分に減少してしまう。 たったこれだけのことをプログラムに取り込むだけで、プログラムのスピードが2倍もアップするではないか (正確に言えば2倍よりずっと少ない効果しかないのだが)。
 素数判定処理には、まだまだ多くの無駄が隠れているのだが、見つけることができるだろうか。 プログラミング・コンテストでは、この無駄を発見することを競うコンテストと言い換えることができるのだ。 このように当たり前のこと「無駄になっている部分を発見し無駄を省けるように手順を作り直す(アルゴリズムの改良)」 ことを常に頭の中においてプログラムを作ることでプログラムの処理速度を高める第一歩となっているのだ。

 手順の変更は少なく、プログラムの変更部分も少なくてすム。プログラムの手順を組み替えて見ると次のようになるだろう。

  1. 打ち切りする上限値を入力する。
  2. 打ち切り数が10,000 を超えておれば10,000とする。
  3. 2 は素数である(明らか)。
  4. スタートする数 J を 3 とする。
  5. 数 J を「素数判定」する。
  6. 素数であれば、素数として表示する。
  7. 数 J を2増やす。
  8. 数 J が上限値未満でれば、処理番号 4 に戻り、処理を継続する。
  9. 数 J が上限値以上であれば、終了する。

 3の倍数までを素数発見のアルゴリズムに取り入れて、アルゴリズムの改良を更に進めた。 その改良アルゴリズムを使って、同じ処理系(Delphi)を使ってプログラムを作成した。 完成したプログラムを使って「10万未満」の部の素数発見を、同じパソコン上でおこなった。 その結果、大きな効果を得ることができた。

「10万未満」の部で 19秒63 → 10秒68 に記録アップ(2倍にスピードアップ)

 原型アルゴリズムで「10万未満」の部が 19秒63 であったものが、 10秒68 までに短縮(スピードアップ)出来ている。およそ2倍のスピードアップが実現できたことになる。 このように、アルゴリズムの改良でプログラムの速度が飛躍的に高まることを体験できたのではないだおうか。 なお、コンテスト本体に影響が及ぶので、このプログラムに関してこれ以上の具体的な解説(アルゴリズム改良)を差し控えることにしよう。

管理人(志)



質問、意見などがありましたら、掲示板、メールなどでお寄せください。


このページは 2003/2/3 に作成されました。