MachiKania type Pの実行速度
2022年7月26日
現在、Raspberry Pi Pico用のMachiKaniaを、ケンケンさんと共同で開発中です。これは、MachiKania Type M, Type ZとコンパチブルなBASICコンパイラーを搭載し、表示装置にLCDを使った、Raspberry Pi Pico用のMachiKaniaで、コードネームにPhyllosomaと名付けたものです。正式名称は、MachiKania Type Pになる予定です。近々、公式にversion 1.0を公開します。
Type MやType Zでは、プログラムの実行にMMC/SDカードやNTSCディスプレイが必要でしたが、Type Pではそういったものが無い環境でもBASICプログラムを高速で実行し、I2CやSPIなどのインターフェースで外部機器を制御することが可能です。従って、組み込み用途でのMachiKania Type Pの利用も、ニーズとしてあると考えています。
Raspberry Pi Pico用には、C/C++による開発環境やMicroPythonによる開発環境がすでに提供されていて、これらはニーズに応じて便利に使えます。C/C++で開発すると最速の実行速度が得られる一方、開発環境の構築に手間がかかり、かつ、外部機器との接続用のSDKの呼び出し方も複雑です。他方で、MicroPythonでの開発は外部機器の制御も分かりやすく、開発にかける時間を少なくできますが、実行速度がそれほど速くはありません。
MachiKaniaはC/C++と同じコンパイル形式なので、最速でないにせよ、ある程度の高速実行が可能です。また、Pythonほど強力ではありませんが、オブジェクト指向プログラミングも可能です。
そこで、MachiKaniaの利便性を評価するため、MachiKania・C/C++・MicroPythonで、実行速度の差がどれぐらいあるのか、調べてみました。
速度測定に利用したC/C++コンパイラー (gcc)、MicroPython、MachiKania Type Pのバージョンは、次の通りです。
ベンチマークテストに使ったプログラムは、古のPCのベンチマークによく使われていてASCIIARTと呼ばれている、マンデルブロ集合を表示するものを使いました。
gcc用には以下のコード。
MicroPython用には以下のコード。
MachiKania用には以下のコード。
gccの実行結果。

MicroPythonの実行結果。

MachiKaniaの実行結果。

実行結果の最後に、計算に要した時間を、μ秒で表示しています。この結果から、CはMachiKaniaより2.31倍速く、MachiKaniaはMicroPythonより4.56倍速いことが分かりました。
上のテストでは、Raspberry Pi Pico上で計算し、結果をPC側にUSB接続を使って転送しています。この転送手続きは115200 bpsのCOM接続で行われているため、ある程度の遅延を生じます。そこで、結果の表示は行わず計算だけ行なった場合の速度についても、比較してみました。
gccのコード。
MicroPythonのコード。
MachiKaniaのコード。
gccの実行結果
MicroPythonの実行結果。

MachiKaniaの実行結果。

この場合、CはMachiKaniaより2.42倍速く、MachiKaniaはMicroPythonより7.11倍速いことが分かりました。
上のテストから、組み込み開発用途としてのMachiKania Type Pの立ち位置は
といった所になりそうです。加えて、MachiKaniaはゲーム開発のためのプラットフォームですから、LCD表示型のゲームを作るのに便利であることは言うまでもありません。
Type MやType Zでは、プログラムの実行にMMC/SDカードやNTSCディスプレイが必要でしたが、Type Pではそういったものが無い環境でもBASICプログラムを高速で実行し、I2CやSPIなどのインターフェースで外部機器を制御することが可能です。従って、組み込み用途でのMachiKania Type Pの利用も、ニーズとしてあると考えています。
Raspberry Pi Pico用には、C/C++による開発環境やMicroPythonによる開発環境がすでに提供されていて、これらはニーズに応じて便利に使えます。C/C++で開発すると最速の実行速度が得られる一方、開発環境の構築に手間がかかり、かつ、外部機器との接続用のSDKの呼び出し方も複雑です。他方で、MicroPythonでの開発は外部機器の制御も分かりやすく、開発にかける時間を少なくできますが、実行速度がそれほど速くはありません。
MachiKaniaはC/C++と同じコンパイル形式なので、最速でないにせよ、ある程度の高速実行が可能です。また、Pythonほど強力ではありませんが、オブジェクト指向プログラミングも可能です。
そこで、MachiKaniaの利便性を評価するため、MachiKania・C/C++・MicroPythonで、実行速度の差がどれぐらいあるのか、調べてみました。
速度測定に利用したC/C++コンパイラー (gcc)、MicroPython、MachiKania Type Pのバージョンは、次の通りです。
gcc: GNU Arm Embedded Toolchain Version 10-2020-q4-major Raspberry Pi Pico C/C++ SDK Version 1.4.0 MicroPython: Raspberry Pi Pico MicroPython Version 1.19.1 MachiKania: MachiKania Type P Version 0.9.2また、実行はすべて、TeraTerm (version 4.106)からUSB-serialで、115200 bpsで接続した状態で行いました。
ベンチマークテストに使ったプログラムは、古のPCのベンチマークによく使われていてASCIIARTと呼ばれている、マンデルブロ集合を表示するものを使いました。
gcc用には以下のコード。
#include <stdio.h>
#include "pico/stdlib.h"
int main() {
int i,x,y,flag,ct;
float a,b,t,ca,cb;
stdio_init_all();
sleep_ms(3000);
ct=time_us_32();
for(y=-13;y<14;y++){
for(x=-39;x<40;x++){
ca=(float)x*0.0458;
cb=(float)y*0.08333;
a=ca;
b=cb;
flag=0;
for(i=0;i<16;i++){
t=a*a-b*b+ca;
b=2*a*b+cb;
a=t;
if ((a*a+b*b)>4) {
flag=1;
break;
}
}
if (!flag) {
putchar(' ');
} else {
if (i>9) i=i+7;
putchar(48+i);
}
}
putchar(0x0d);putchar(0x0a);
}
printf("%d\n",time_us_32()-ct);
while(1);
return 0;
}MicroPython用には以下のコード。
import time
time.sleep(1.0)
start=time.ticks_us()
for y in range(-13,14):
for x in range(-39,40):
ca=x*0.0458
cb=y*0.08333
a=ca
b=cb
flag=0
for i in range(0,16):
t=a*a-b*b+ca
b=2*a*b+cb
a=t
if (a*a+b*b)>4:
flag=1
break
if flag==0:
print(" ",end="")
else:
if i>9:i=i+7
print(chr(48+i),end="")
print("")
print(time.ticks_us()-start)MachiKania用には以下のコード。
USEVAR CA,CB,FLAG
Z=CORETIMER()
FOR Y=-13 TO 13
FOR X=-39 TO 39
CA#=FLOAT#(X)*0.0458
CB#=FLOAT#(Y)*0.08333
A#=CA#
B#=CB#
FLAG=0
FOR I=0 TO 15
T#=A#*A#-B#*B#+CA#
B#=2*A#*B#+CB#
A#=T#
IF (A#*A#+B#*B#)>4 THEN
FLAG=1
BREAK
ENDIF
NEXT
IF FLAG=0 THEN
PRINT " ";
ELSE
IF I>9 THEN I=I+7
PRINT CHR$(48+I);
ENDIF
NEXT
PRINT
NEXT
PRINT CORETIMER()-Z
A$=INPUT$()
(ただし、MACHIKAP.INIで「LCDOUTOFF」を指定)gccの実行結果。

MicroPythonの実行結果。

MachiKaniaの実行結果。

実行結果の最後に、計算に要した時間を、μ秒で表示しています。この結果から、CはMachiKaniaより2.31倍速く、MachiKaniaはMicroPythonより4.56倍速いことが分かりました。
上のテストでは、Raspberry Pi Pico上で計算し、結果をPC側にUSB接続を使って転送しています。この転送手続きは115200 bpsのCOM接続で行われているため、ある程度の遅延を生じます。そこで、結果の表示は行わず計算だけ行なった場合の速度についても、比較してみました。
gccのコード。
#include <stdio.h>
#include "pico/stdlib.h"
static volatile unsigned char g_dummy_char;
#define putchar(a) do {\
g_dummy_char=a;\
} while(0)
int main() {
int i,x,y,flag,ct;
float a,b,t,ca,cb;
stdio_init_all();
sleep_ms(3000);
ct=time_us_32();
for(y=-13;y<14;y++){
for(x=-39;x<40;x++){
ca=(float)x*0.0458;
cb=(float)y*0.08333;
a=ca;
b=cb;
flag=0;
for(i=0;i<16;i++){
t=a*a-b*b+ca;
b=2*a*b+cb;
a=t;
if ((a*a+b*b)>4) {
flag=1;
break;
}
}
if (!flag) {
putchar(' ');
} else {
if (i>9) i=i+7;
putchar(48+i);
}
}
putchar(0x0d);putchar(0x0a);
}
printf("%d\n",time_us_32()-ct);
while(1);
return 0;
}MicroPythonのコード。
import time
time.sleep(1.0)
start=time.ticks_us()
for y in range(-13,14):
for x in range(-39,40):
ca=x*0.0458
cb=y*0.08333
a=ca
b=cb
flag=0
for i in range(0,16):
t=a*a-b*b+ca
b=2*a*b+cb
a=t
if (a*a+b*b)>4:
flag=1
break
if flag==0:
pass #print(" ",end="")
else:
if i>9:i=i+7
#print(chr(48+i),end="")
#print("")
print(time.ticks_us()-start)MachiKaniaのコード。
USEVAR CA,CB,FLAG
Z=CORETIMER()
FOR Y=-13 TO 13
FOR X=-39 TO 39
CA#=FLOAT#(X)*0.0458
CB#=FLOAT#(Y)*0.08333
A#=CA#
B#=CB#
FLAG=0
FOR I=0 TO 15
T#=A#*A#-B#*B#+CA#
B#=2*A#*B#+CB#
A#=T#
IF (A#*A#+B#*B#)>4 THEN
FLAG=1
BREAK
ENDIF
NEXT
IF FLAG=0 THEN
rem PRINT " ";
ELSE
IF I>9 THEN I=I+7
rem PRINT CHR$(48+I);
ENDIF
NEXT
rem PRINT
NEXT
PRINT CORETIMER()-Z
A$=INPUT$()
(ただし、MACHIKAP.INIで「LCDOUTOFF」を指定)gccの実行結果

MicroPythonの実行結果。

MachiKaniaの実行結果。

この場合、CはMachiKaniaより2.42倍速く、MachiKaniaはMicroPythonより7.11倍速いことが分かりました。
上のテストから、組み込み開発用途としてのMachiKania Type Pの立ち位置は
- Cで開発した場合の半分ぐらいの速度で、高速実行できる
- 実行速度は、MicroPythonより数倍速い
- オブジェクト指向型BASICを用いて、容易にコードを組むことができる
- LCDとMMCカードのライブラリーが組み込まれており、制御が容易
- PWM、SPI、I2C、UART、ADCのライブラリーが組み込まれており、制御が容易
といった所になりそうです。加えて、MachiKaniaはゲーム開発のためのプラットフォームですから、LCD表示型のゲームを作るのに便利であることは言うまでもありません。