2019年08月07日 | 公開。 |
FASTIOライブラリには次の様な特徴があります。
FASTIOライブラリを使うと、Arduino本体のデジタルI/Oピン(GPIO)へのアクセスが高速化します。
Arduino標準のdigitalWrite関数およびdigitalRead関数によるそれぞれ10万回の入力および出力にかかった時間と、同様の操作をFASTIOを使って行った場合にかかった時間を、表2に示します。出力時には約22倍、入力時には約32倍の高速化ができている様子が分かります。
Arduino標準関数を使った場合の実行時間 | FASTIOライブラリを使った場合の実行時間 | |
---|---|---|
出力(digitalWrite関数) | 336ms(リスト1で計測) | 15ms(リスト2で計測) |
入力(dititalWrite関数) | 291ms(リスト3で計測) | 9ms(リスト4で計測) |
注:計測はArduino Unoで行いました。また、コンパイルはArduino IDE 1.8.5で行いました。計測に使ったスケッチのリストをリスト1~リスト4に示します。
void setup()
{
Serial.begin(9600); // シリアルポートを9600bpsで開く
pinMode(13,OUTPUT); // 13番ピンを出力に設定
} // setup
void loop() {
uint32_t start, stop; // 実行時間を計測するための変数
start=millis(); // 計測開始時刻の取得
for(int i=0; i<10000; i++) { // digitalWrite関数を10万回呼び出す
digitalWrite(13,HIGH);
digitalWrite(13,LOW);
digitalWrite(13,HIGH);
digitalWrite(13,LOW);
digitalWrite(13,HIGH);
digitalWrite(13,LOW);
digitalWrite(13,HIGH);
digitalWrite(13,LOW);
digitalWrite(13,HIGH);
digitalWrite(13,LOW);
} // for i
stop=millis(); // 計測終了時刻の取得
Serial.println(stop-start); // 実行時間をms単位で表示
} // loop
#include <fastio.h> // FASTIOライブラリのヘッダファイルをインクルード
void setup()
{
Serial.begin(9600); // シリアルポートを9600bpsで開く
pinMode(13,OUTPUT); // 13番ピンを出力に設定
} // setup
void loop() {
uint32_t start, stop; // 実行時間を計測するための変数
start=millis(); // 計測開始時刻の取得
for(int i=0; i<10000; i++) { // digitalWrite関数を10万回呼び出す
digitalWrite<13>(HIGH); // FASTIOライブラリのdigitalWrite関数の呼び出し。第1引数が<13>と、山括弧で囲まれている事に注意。
digitalWrite<13>(LOW);
digitalWrite<13>(HIGH);
digitalWrite<13>(LOW);
digitalWrite<13>(HIGH);
digitalWrite<13>(LOW);
digitalWrite<13>(HIGH);
digitalWrite<13>(LOW);
digitalWrite<13>(HIGH);
digitalWrite<13>(LOW);
} // for i
stop=millis(); // 計測終了時刻の取得
Serial.println(stop-start); // 実行時間をms単位で表示
} // loop
void setup()
{
Serial.begin(9600); // シリアルポートを9600bpsで開く
pinMode(13,INPUT_PULLUP); // 13番ピンを入力(プルアップ付き)に設定
} // setup
void loop() {
uint32_t start, stop; // 実行時間を計測するための変数
start=millis(); // 計測開始時刻の取得
for(int i=0; i<10000; i++) { // digitalRead関数を10万回呼び出す
int data; // 入力の結果を格納する変数
data=digitalRead(13);
data=digitalRead(13);
data=digitalRead(13);
data=digitalRead(13);
data=digitalRead(13);
data=digitalRead(13);
data=digitalRead(13);
data=digitalRead(13);
data=digitalRead(13);
data=digitalRead(13);
} // for i
stop=millis(); // 計測終了時刻の取得
Serial.println(stop-start); // 実行時間をms単位で表示
} // loop
#include <fastio.h> // FASTIOライブラリのヘッダファイルをインクルード
void setup()
{
Serial.begin(9600); // シリアルポートを9600bpsで開く
pinMode(13,INPUT_PULLUP); // 13番ピンを入力(プルアップ付き)に設定
} // setup
void loop() {
uint32_t start, stop; // 実行時間を計測するための変数
start=millis(); // 計測開始時刻の取得
for(int i=0; i<10000; i++) { // digitalRead関数を10万回呼び出す
int data; // 入力の結果を格納する変数
data=digitalRead<13>(); // FASTIOライブラリのdigitalRead関数の呼び出し。第1引数が<13>と、山括弧で囲まれている事に注意。
data=digitalRead<13>();
data=digitalRead<13>();
data=digitalRead<13>();
data=digitalRead<13>();
data=digitalRead<13>();
data=digitalRead<13>();
data=digitalRead<13>();
data=digitalRead<13>();
data=digitalRead<13>();
} // for i
stop=millis(); // 計測終了時刻の取得
Serial.println(stop-start); // 実行時間をms単位で表示
} // loop
念のために、リスト1(Arduino標準のdigitalWrite関数を使用)を実行した場合と、リスト2(FASTIOライブラリのdigitalWrite関数を使用)を実行した場合について、13番ピンの出力波形をロジックアナライザで観察してみました。
リスト1の実行時の出力波形を図1に、リスト2の実行時の出力波形を図2に示します。これらの波形からも、FASTIOライブラリを使う事により、digitalWrite関数の実行が二十数倍に速くなっている事が確認できます。
ばらつきがあるものの、digitalWrite関数1回の実行に、3.2~3.4μs(3200~3400ns)程度の時間がかかっている事が分かります。16MHzのArduino Unoのクロック周期は62.5nsですから、1回のdigitalWrite関数の実行に3300nsかかっているとして、3300÷62.5=52.8クロック程度の実行サイクルが必要な事が分かります。出力がLになっている期間がHになっている期間より短い傾向が観察できるので、Lを出力する場合とHを出力する場合で実行時間が少し違いそうです。この測定は、Arduino starter kit with Logic Analyzer付属のロジックアナライザで行いました。
digitalWrite関数1回の実行に、120~130ns程度の時間がかかっている事が分かります。時々波形のLの期間が380ns程度に広くなっている理由は、digitalWrite関数を10回実行するたびに、forループによる繰り返しがあり、変数iのインクリメント、iの値のチェック、ジャンプ命令などに時間がかかるためです。digitalWrite関数1回の実行に125nsの時間がかかっているとして、125÷62.5=2サイクルで実行できている事が分かります。なお、計測結果が120nsになったり130nsになったりするのは、ロジックアナライザの時間分解能が10nsだからです。
参考:表2に示した、10万回の関数の実行にかかった時間をms単位で表わした数字を10倍して、100万回の関数の実行にかかった時間に換算すれば、1回の関数の実行にかかった時間をns単位で表わした数字に、理屈の上ではなります。表1ではリスト1の実行に336msかかっていますから、関数1回あたり3360nsかかっている計算になります。これは、図1に示したロジックアナライザで測定した結果によく一致しています。また、表1ではリスト2の実行に15msかっかっていますから、関数1回あたり150nsかかっている計算になります。図2に示したロジックアナライザによる測定結果(120~130ns)より少し長めに出ているのは、forループによるオーバーヘッドも含めて計測しているからだと推測できます。(リスト1の場合は、digitalWrite関数の実行に長い時間がかかっているので、forループによるオーバーヘッドはあまり問題になりません)
次のページでは、FASTIOライブラリのその他の特徴について説明します。