MachiKania

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のバージョンは、次の通りです。
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の実行結果。
2022-07-26-c101.png
MicroPythonの実行結果。
2022-07-26-c102.png
MachiKaniaの実行結果。
2022-07-26-c103.png

実行結果の最後に、計算に要した時間を、μ秒で表示しています。この結果から、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の実行結果2022-07-26-c201.png
MicroPythonの実行結果。
2022-07-26-c202.png
MachiKaniaの実行結果。
2022-07-26-c203.png

この場合、CはMachiKaniaより2.42倍速く、MachiKaniaはMicroPythonより7.11倍速いことが分かりました。

上のテストから、組み込み開発用途としてのMachiKania Type Pの立ち位置は

  1. Cで開発した場合の半分ぐらいの速度で、高速実行できる
  2. 実行速度は、MicroPythonより数倍速い
  3. オブジェクト指向型BASICを用いて、容易にコードを組むことができる
  4. LCDとMMCカードのライブラリーが組み込まれており、制御が容易
  5. PWM、SPI、I2C、UART、ADCのライブラリーが組み込まれており、制御が容易

といった所になりそうです。加えて、MachiKaniaはゲーム開発のためのプラットフォームですから、LCD表示型のゲームを作るのに便利であることは言うまでもありません。

コメント

コメントはありません

コメント送信