E500BASIC高速化のすべて

PART 4 どうやったらBASICが高速化できるのか


 速度に不満のあるBASICプログラムでも工夫次第で処理速度の向上が見込めるということは分かったと思いますが、実際にはどのような過程で行えば良いのか分からないという人もいるかと思います。そうわけでこれからは具体的な方法を書いていくことにします。
 なお、これから先はBASICで普通にプログラミングができるレベル(中級者以上)の方のみ読むことをおすすめします。普通に作ることさえまだ満足にできないレベル(初級者)の人は高速化を行うことでさらなる混乱を招く元になりますからね。

 BASICの高速化においては大きく分けて下記の5つの方法があります。
(1)要らないものは省略もしくは簡単なものに置き換え
(2)アルゴリズムの見直し
(3)メインルーチンの軽量化
(4)表示を高速化
(5)IF文をうまく使う

 これは誰でも簡単にできる(1)を除けば高速化において最も無駄が少ない順番となっています。これはボトルネックになっている部分が分からない人向けなので、すでにボトルネックとなっている部分が分かっていればこの順番に拘る必要はなくその部分を優先的に改善すべきでしょう。



 まずは(1)から見てみましょう。
 多くの人が知っているような例を挙げるならばFOR〜NEXTにおいてNEXTの後の変数は省略できそれによって高速化が可能だったり、THENを省略する(もしくはLETに置き換える)ことで高速化ができるようになるといったそういう類のものです。
 ただ、THENをLETに置き換えるというのはメジャーな方法ですが、それは単体では高速化効果は極めて低いものとなっています。THENLETに1つ置き換えることにより0.09m秒速くなりますが、これを1ttl(then to let)という単位で表記することにします。つまり、1ttl≒0.09m秒となります。

THENをLETに置き換え1 ttl高速化)
コロン「:」をコンマ「,」に置き換え2 ttl高速化)
カッコを省略5 ttl高速化)
NEXTの後の変数を省略8 ttl高速化)
配列変数を固定変数に置き換え20 ttl高速化)
16進数(&付き数値)を10進数に置き換え40 ttl高速化)

 わざわざ実速度ではなくこんなオリジナル単位(ttl)を使うのは実速度を書いてもそれぞれの高速化効果が分かりにくいので相対比較がしやすいようにしたためです。あと演算速度は数値によって微妙に変わってくるため正確な値というものが存在しないためです。

 コロンをコンマに置き換えが可能なのはマルチステートメントで記述している時に変数への代入処理が連続する時です。
 乗算(18 ttl)は加算(8 ttl)よりも処理に時間がかかるためB=A*2B=A+Aと置き換えることで高速化可能になります。また、定数はE500系では1桁でも8バイトとなってしまうため7バイトのメモリ節約ができます。しかし、B=A*3B=A+A+Aとするとかえって遅くなってしまいます。乗算は加算の2倍以上遅いから3倍を行う場合は加算で処理した方が速くはずと思うかもしれません。それは固定変数であっても処理に相当の時間(8 ttl)がかかるからです。
 またB=A*AB=SQU Aとした方が速くできます。乗算(18 ttl)よりもSQU24 ttl)の方が処理が遅いのですが、上記のように固定変数の処理に時間がかかっているため速度は逆転しています。ちなみに3乗はB=A*A*AB=A^3よりは速いのですがB=CUB Aとした方がが速くなります。

 変数の処理に関しては固定変数が最も速いのですが、それでも上記のように処理に8ttlくらいの時間を要してしまいます。配列変数は固定変数よりも遅いというのも上記の通りですが、単純変数(変数名に2文字以上使用したもの)も固定変数よりも遅くなります。固定変数の場合は格納されているアドレスが固定なのですが、単純変数や配列変数の場合は格納アドレスが可変のため読み出し処理自体に時間がかかってしまいます。また、変数名の認識処理にも時間がかかるため単純変数の場合は変数名の文字数が増えれば増えるほど遅くなってしまいます。メインルーチン内での使用頻度が高い変数は極力固定変数を使うことが高速化において重要になってきます。また、確保した順番によって処理時間が変わってくるのでどうしてもメインルーチン内で単純変数を使用しなくてはならない場合は使用頻度の高いものをなるべく先に宣言(というか変数の初期化をしてメモリ上に領域を確保)しておいた方が良いです。

 べき乗演算はBASICの演算子の中ではかなり重い(数100ttl)ものなので計算式を簡略化して高速化を用いるという方法もあります。
 E500の場合はPOKEやPEEK以外でも16進数を使用しているものが多いですが、それは上記のように数値は桁数に関係なく8バイトのメモリを消費してしまうからです。「7→&7」のように&を付け16進数化(「0」は「&0」ではなく「&」単体でOK)すれば見た目の文字数しかメモリ消費がないためにメモリを節約が可能になります。メモリ節約の面があるので速度を要求している部分のみ10進数で表記、速度は気にならない部分に関しては16進数で表記するという使い分けをするという選択もあります。(メインルーチン内ではPOKEやPEEK使用時でも16進数ではなく10進数で表記することで高速化ができる)
 マルチステートメントを多用することで改行処理を省略したり、REM(’)を省略するのも高速化に繋がりますがこれらはあまりやりすぎるとリストが見にくくなるのでほどほどにしておいて方がよいでしょう。

 このように普段使わない関数(命令)の中には高速化によって有用なものも多くあります。高速化を行うならばそれらを積極的にどんどん使っていきましょう。ただ、1つ1つの高速化の効果はそれほど高くありません。高速化の効果が体感できるレベルに達するのはかなり難しいですが、「ちりも積もれば(略)」と昔から言うように小さなことからコツコツやっていくのも重要だと思います。
 後述の高速化を行った時には特にその効果が出てきます。仮に初期状態でメインルーチン1回あたりの処理時間が200m秒でこのPART4に書いてあることを実戦しても20m秒しか速くならなければ速度向上率は11%となり体感で速度向上を感じるのは難しいですが、メインルーチンの処理時間が60m秒になれば20m秒の高速化は速度向上率は50%になります。これならば「VS」→「VSターボ」の速度向上率よりも大きいため体感でも明らかに速くなったことが分かるでしょう。だからこの省略による高速化はこれだけを行えば良いというものではなく他の高速化方法と併用して初めてその真価を発揮できるものといえます。

PART5に続く


PART 1 なぜBASICを高速化するのか
PART 2 効率的な高速化を行うためには
PART 3 BASICの高速化とは
PART 4 どうやったらBASICが高速化できるのか
PART 5 アルゴリズムの見直し
PART 6 メインルーチンの軽量化
PART 7 表示を高速化
PART 8 IF文をうまく使う
PART 9 「BASICだから遅い」は言い訳の言葉

RETURN

inserted by FC2 system