高速処理の為のプログラミング
秋月300円液晶の制御は大量のデータを扱います。
動画の表示では一秒間で3MB以上のデータ転送が必要になったりします。
本を読んだりプログラミングをしている内に、高速に処理する為の工夫が2つ程
見つかったので備忘録として記録します。
①大量に同じ処理をする場合にfor文やwhile文の分岐を減らす
②単純なメモリ間のデータ転送はint型(STM32なら32bit)にポインタをキャストして転送する。
①大量に同じ処理をする場合にfor文やwhile文の分岐を減らす
配列memory からpeliphへデータをコピーする場合を考えてみます。
とりあえず、普通のプログラム。
#define DISPLAY_WIDTH 400
#define BUFFER_LINE_SIZE 28
int i = 0;
for(i = 0 ; i < (DISPLAY_WIDTH * BUFFER_LINE_SIZE) ; i++)
{
memory[i] = peliph[i];
}
うん、スッキリしているね。
でもね・・・遅いんだよぉぉぉ!!
1行処理する度に、(コピーに寄与しない)分岐命令が入るため、遅延が凄いんです。
分岐命令自体の処理サイクル遅延はもちろんですが、
STM32のフラッシュ読み込みは2サイクル(72MHz)必要で、それを解消するために
プリフェッチバッファがあるのですが、分岐命令のせいで
プリフェッチされた命令がキャンセルされたりします。
つまり、処理速度と命令読み出し速度の2点から分岐命令はイクナイ!のです。
そこで下のように書き直します。
高速化されたプログラム
#define DISPLAY_WIDTH 400
#define BUFFER_LINE_SIZE 28
int i = 0;
int k = 0;
/* DISPLAY_WIDTHの回数分命令を繰り返してfor分岐を無くす */
for(i =0 ; i < BUFFER_LINE_SIZE ; i++)
{
memory[k] = peliph[k];
k++;
memory[k] = peliph[k];
k++;
memory[k] = peliph[k];
k++;
.
.
.
×400回くらい
}
DISPLAY_WIDTH の分、繰り返し命令ではなく
ソースコードを繰り返す事で分岐遅延を無くしています。
ソースコードなげぇぇぇ!!ってなりますが
処理速度は数倍速くなります。
ROMもふんだんに使いますが、STBeeは512kB。楽勝だね!
②単純なメモリ間のデータ転送はint型(STM32なら32bit)にポインタをキャストして転送する。
8bit変数の配列から8bit変数の配列へのコピーを考えます。
pic_dataの501個目を
mov_dataの201個目へとコピーしていきます
普通のプログラム
byte pic_data[1000];
byte mov_data[700];
byte *pic_ptr;
byte *move_ptr;
pic_ptr = &pic_data[500];
move_ptr = &move_data[200];
int i = 0;
for(i =0 ; i <500 ; i++)
{
*move_ptr = *pic_ptr ;
pic_ptr++ ;
move_ptr++ ;
}
普通にプログラミングしてたらこんな感じになると思います。
これも早く処理する事ができます。
STM32は32bitマイコンですので32bit単位での転送が
CPU的に自然で処理が早いのです。
よってポインタを32bitのint型でキャストします。
高速化されたプログラム
byte pic_data[1000];
byte mov_data[700];
int *pic_ptr;
int *move_ptr;
pic_ptr = (int *)&pic_data[500];
move_ptr = (int *)&move_data[200];
int i = 0;
/* 32bit長で転送するので繰り返し数を4分の1に。 */
for(i =0 ; i <125 ; i++)
{
*move_ptr = *pic_ptr ;
pic_ptr++ ;
move_ptr++ ;
}
これで4倍速です。
byte型の変数配列だからってbyte単位で転送しなくても良いのですね。
高速処理したいけれど、配列数が32bitの倍数ではないという場合は
32bitの倍数へとnullを1~3byte突っ込んででも
配列を拡張すればよいと思います。
また、余談ですが今回のプログラムの i はuint16_t型でも利用できますが
32bitマイコンではわざわざ16bit→32bitへ暗黙的変換が行われ
処理が遅延する場合があるので、int型にしておく方が処理速度的に安心です。
この方法は多分、組み込みプログラミングをされている方なら
常識なのでしょうが、私は知らなかったので備忘録として記載しておきます。
以上です。
プログラミングとしての美しさは損なわれ、可読性も落ちてしまいますが
それでも限られたCPUパワーの中で高速に処理する為には
必要であると感じています。
ここが組み込みとPCプログラミングの違いなんでしょうね。