性能測定実験(I/O)
UNO

概要

Arduino UnoのIOの性能測定を行いました。

当初、Arduino 1.0で測定した結果を掲載していました。Arduino 1.8.12でも再度測定しました。Arduino IDEのバージョンにより、デジタルI/Oの性能がかなり違う結果が出てきました。

目的

Arduino UnoのdigitalRead()digitalWrite()analogRead()の3つの関数の性能を、ピンごとに測定し、特性を調べます。

測定方法

各関数を10000回実行し、その前後でmicros()を使って時刻を取得し、測定後、1回あたりの各関数の実行時間を測定します。このため、ループを制御するための時間も含んでいます。

Arduinoには何も接続しない状態で、デジタルピンはdigitalRead()digitalWrite()の2種類、アナログピンはさらにanalogRead()の実行時間を取得しました。digitalRead()analogRead()の実行結果は、volatile宣言した変数に代入しました。analogRead()は、計測前にに1回実行した後、10000回実行しています。

実験結果

Arduino 1.8.12とArduino 1.0とで測定した結果を示します。単位はマイクロ秒です。

Arduino 1.8.12では、1回だけ測定しました。Arduino 1.1では、2回実行しました。1回目と2回目とで値が異なったものはありませんでした。

Arduino 1.8.12

ピン番号 digitalRead() digitalWrite() analogRead()
0 3.52 3.14 -
1 3.52 3.14 -
2 3.52 3.14 -
3 4.90 4.53 -
4 3.52 3.14 -
5 4.72 4.34 -
6 4.46 4.09 -
7 3.52 3.14 -
8 3.52 3.14 -
9 4.40 4.02 -
10 4.97 4.59 -
11 4.65 4.28 -
12 3.52 3.14 -
13 3.52 3.14 -
14 3.52 3.14 112.00
15 3.52 3.14 112.00
16 3.52 3.14 112.00
17 3.52 3.14 112.00
18 3.52 3.14 112.00
19 3.52 3.14 112.00

Arduino 1.0

ピン番号 digitalRead() digitalWrite() analogRead()
1回目2回目1回目2回目1回目2回目
04.404.404.284.28--
14.404.404.284.28--
24.404.404.284.28--
35.225.225.165.16--
44.404.404.284.28--
55.225.225.165.16--
65.165.165.095.09--
74.404.404.284.28--
84.344.344.284.28--
95.095.094.974.97--
105.535.535.475.47--
115.225.225.165.16--
124.344.344.284.28--
134.344.344.284.28--
14(アナログ0)4.344.344.284.28112.01112.00
15(アナログ1)4.344.344.284.28112.01112.00
16(アナログ2)4.344.344.284.28112.01112.00
17(アナログ3)4.344.344.284.28112.01112.00
18(アナログ4)4.344.344.284.28112.01112.00
19(アナログ5)4.344.344.284.28112.01112.00

考察

Arduino 1.8.12

(私の)Arduino Unoでは、digitalRead()は約3.52~4.97マイクロ秒、digitalWrite()は3.14マイクロ秒~4.59マイクロ秒、analogWrite()は約112マイクロ秒かかることがわかりました。ただし、ループ時間込なので実際にはもう少し短い時間で実行できていると思います。

Arduino 1.0

(私の)Arduino Unoでは、digitalRead()は約4.34~5.53マイクロ秒、digitalWrite()は4.28マイクロ秒~5.47マイクロ秒、analogWrite()は約112マイクロ秒かかることがわかりました。ただし、ループ時間込なので実際にはもう少し短い時間で実行できていると思います。

共通

ピンごとに見ると、3・5・6・9・10・11の6つのピンは他のピンと比べてデジタル入出力の性能が(わずかですが)悪いことがわかります。これらのピンは、PWM出力ができるピンと同じです。digitalRead()digitalWrite()Arduinoのソースコードを見てみると、PWM出力可能なピンでは、PWM出力をOFFにするという操作を行っていました。このぶん他のピンに比べて余分に時間がかかっているようです。

ほんの少しでも性能を求めるアプリケーションであれば、PWM出力ができないピンを利用するのがいいと思われます。さらに性能を求める場合は、PORTレジスタを用いるのがいいと思います。簡単に試した結果、読み書きとも1マイクロ秒かからないで実行できました。

analogRead()のリファレンスには、約100マイクロ秒かかる(“It takes about 100 microseconds (0.0001 s) to read an analog input”)と書いてあり、ほぼそのような結果となりました。

Arduino IDEのバージョンにより測定値が異なる原因までは追究していませんが、ハードウェアは同じなので、IDEそのものの実装を効率化したか、コンパイラの性能と思います。この実験ではループの時間まで測定してしまっているので。

スケッチ

今回の実験に使用したスケッチを以下に示します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
const int repeat = 10000;
 
void measure(int pin) {
  long begin, end;
  volatile int val;
   
  Serial.print("Pin No.: ");
  Serial.println(pin);
 
// digitalRead()
  pinMode(pin, INPUT);
  delay(1000);
  begin = micros();
  for(int i = 0; i < repeat; i++) {
    val = digitalRead(pin);
  }
  end = micros();
   
  Serial.print("  digitalRead:    ");
  Serial.println((end - begin) / (float)repeat);
 
// digitalWrite()
  pinMode(pin, OUTPUT);
  delay(1000);
  begin = micros();
  for(int i = 0; i < repeat; i++) {
    digitalWrite(pin, HIGH);
  }
  end = micros();
   
  Serial.print("  digitalWrite:   ");
  Serial.println((end - begin) / (float)repeat);
   
// analogRead()
  if ((pin >= A0) && (pin <= A5)) {
    val = analogRead(pin);
    begin = micros();
    for(int i = 0; i < repeat; i++) {
      val = analogRead(pin);
    }
    end = micros();
   
    Serial.print("  analogRead:   ");
    Serial.println((end - begin) / (float)repeat); 
  }
   
  Serial.println();
}
   
void setup () {
  int pin;
   
  Serial.begin(9600);
   
  for(pin = 0; pin < 20; pin++) {
    measure(pin);
  }
}
 
void loop () {
}

バージョン

Hardware:Arduino Uno
Software:Arduino 1.0/Arduino 1.8.12

最終更新日

January 23, 2021

inserted by FC2 system