ガベージコレクタを追加(RPiベアメタルMicroPython)

mandelbrot-rpi.jpg

Raspberry Pi上のMicroPythonで、フレームバッファにマンデルブロ集合を描かせてみました。
コードはこちらです。

このコードは、以前ESP32でも試したこちらのコードの移植版です。

しかし、半分ほどまで進んだところでMemory Errorで止まってしまいました。
ガベージコレクタを実装していなかったので、ヒープを使い切ると止まってしまうのでした。(実は現状ではヒープには128MBしか割り当てていません)
Raspberry Piはメモリが多いので、あまり気にしていなかったのですが、上記のように長いループを回すのはさすがに無理があったようです。

ガベージコレクタはMicroPythonの処理系に機能は含まれていて呼び出すだけですが、呼ぶ前にレジスタを保存する必要があります。
この部分は、STM32用の実装をほぼ変更無しにそのまま利用できました。

上記のマンデルブロ集合を描かせた後、手動でGCさせてみたところ、以下のようにかなりメモリを使っていました。
(これ以前に、おそらく実行中に1度はGCしているはずです。)

>>> import gc
>>> gc.mem_free()
12535552
>>> gc.mem_alloc()
119617360
>>> gc.collect()
>>> gc.mem_free()
132151200
>>> gc.mem_alloc()
1712
>>>

ちなみにMicroPythonのガベージコレクタは、マーク・アンド・スイープ方式です。
他のオブジェクトから参照されていないオブジェクトは開放されます。
参照関係の大元はroot pointerで、root pointerから辿れないオブジェクトはGCの対象になります。

Memory allocation and deallocation – MicroPython Forum

このあたりのことは、以前USBホストコントローラを実装するときにちょっと書きましたが、Cで動的に確保したメモリをGCの対象から外すには、MICROPY_PORT_ROOT_POINTERSにポインタを追加した上で、ポインタの参照には常にMP_STATE_PORT()マクロで囲う必要があります。

コメント