hzeller / rpi-rgb-led-matrix

Controlling up to three chains of 64x64, 32x32, 16x32 or similar RGB LED displays using Raspberry Pi GPIO
GNU General Public License v2.0
3.64k stars 1.16k forks source link

Python 64x64 expected performance #710

Open tohox opened 5 years ago

tohox commented 5 years ago

Hi,

I'm using a 64x64 matrix (the one sold by Adafruit) with their bonnet to display cycling animations. I'm doing this using Python 2.7 both on a PiZero W and Pi 3B+ although I would much prefer to use the PiZero for space concerns. I'm using PipaOS 6 a lightweight variant of Raspbian Stretch in both cases.

I'm cycling though 64x64 PNG images with transparent backgrounds approximately 30 times per second using the CreateFrameCanvas() and SwapOnVSync() technique. While the image refresh rate is just barely sufficient on the Pi Zero it appears smooth on the Pi3B+ but on both boards I get noise consisting of horizontal lines flashing in random positions which I don't get at all when running the C++ demos (on either board). When I set show_refresh_rate to True in my script I get approximately 80Hz on the PiZero and about 130Hz on the Pi3B+. Top shows about 70% CPU usage on both boards while the script is running.

Does this correspond to expected performance when using Python or am I doing something wrong? Should I revert to C++ to get perfect playback?

Raspberry Pi Zero W video Raspberry Pi 3B+ video

Thanks!

hzeller commented 5 years ago

Problem is that Python has garbage collection, so will have a much higher memory throughput that you can't control from the language; unfortunately, the memory bus on the Pi seems to be pretty limited, so if there are many things competing for the memory bus, you will see issues. I suspect part of this is what you are seeing. Using CreateFrameCanvas() initially and then doing SwapOnVSync() sounds like is already the best you can do, as you minimize any additional unnecessary allocation.

What you definitely want to do is to use the hardware PWM hack (needed for both the Adafruit HAT and Bonnet) https://github.com/hzeller/rpi-rgb-led-matrix#improving-flicker - it will almost eliminate the flashing lines issue. You will still get some overall brightness fluctuations, but much less pronounced.

In general, I recommend using the Pi3, as it has four cores, of which you can use one entirely for the display update (using the isolcpus=3 setting described in the README).

On the PiZero devices, you only have a single core which is equivalent to the Raspberry Pi 1 so about factor 10x slower.

Python is pretty slow, in particular on the PiZero type boards, but since you use prepared frame canvases which are mostly a thing handled on the C++ side, it is probably not as problematic. But you still have the overhead of Python garbage collection and possibly other parts messing with the system-speed.

In general of course, C++ is recommended if you want the best speed. You can also use the ready-made LED image viewer if it is sufficient to just display canned animations. But as usual it all depends: if things are 'good enough' with Python, this might be already sufficient.

I suggest to proceed like this