Hallo,
nachdem Norbert (der_norbert) hier immer mal wieder beeindruckende
Zahlen liefert, wie schnell den Micropython auf einem Raspberry Pi Pico
läuft, bin ich auch mal neugierig geworden.
Ich habe mir Micropython nach dem PDF "Raspberry Pi Pico-series Python
SDK" unter Linux installiert und die Runtime auf meinem Raspberry Pi
Pico (ohne W und auch nicht der 2) geflasht.
Die Runtime meldet sich so bei mir:
1
MicroPython v1.25.0-preview.540.g0b3ad98ea on 2025-04-12; Raspberry Pi Pico with RP2040
2
Type "help()" for more information or .help for custom vREPL commands.
Läuft also. Ich kann per Console auf dem Board Code laufen lassen bzw.
der Interpreter ist bedienbar.
Als IDE habe ich mir VS Code genommen. Dort habe ich MicroPico als
Extension installiert und die Extensions die Autocompletion u.s.w.
erledigen.
Dann habe ich ich den Code von hier (von Norbert) laufen lassen:
Beitrag "Re: Micropython rp2040"
Das sind meine Ergebnisse:
1
CPU: 33 MHz 8093 9075 9463 FLOPS/core
2
CPU: 66 MHz 16159 18151 18926 FLOPS/core
3
CPU:133 MHz 32562 36577 38138 FLOPS/core
4
CPU:266 MHz 65126 73153 76276 FLOPS/core
Die von Norbert sind um den Faktor ~1.8 schneller:
1
CPU: 33 MHz 14390 17463 18938 FLOPS/core
2
CPU: 66 MHz 28665 35097 37680 FLOPS/core
3
CPU:133 MHz 57765 70724 75931 FLOPS/core
4
CPU:266 MHz 115990 140767 152656 FLOPS/core
Es ist dabei egal, ob ich den Code mit VSC starte oder mit dem mpremote
tool.
Die Frage, woran liegst? Da der Beispielcode auch den CPU-Takt
einstellt, kann es daran wohl nicht liegen.
Die Runtime sollte doch nicht soviel langsamer geworden sein?
Hat jemand eine Idee? Vielleicht liest Norbert ja mit und hat Lust
seinen Test nochmal laufen zu lassen? Oder jemand anderes lässt ihn mal
laufen?
Wo ist mein Denkfehler? Hat jemand einen Hinweis?
Vielen Dank Euch.
900ss
Nachtrag: Vielleicht liegt der Trick auch im compilieren vom Code. Das
hab ich noch nicht wirklich durchschaut weil die Anweisungen viper bzw
native scheinbar auch vom Interpreter verstanden werden und der Code
ohne diese Anweisungen langsamer läuft wie man an den Ergebnissen sieht.
Nachtrag2: picotool meldet vom Interpreter binary:
900ss schrieb:> Vielleicht liest Norbert ja mit und hat Lust> seinen Test nochmal laufen zu lassen?
Hab ich. Mit 1.24.1
1
CPU: 33 MHz 8356 9177 9483 FLOPS/core
2
CPU: 66 MHz 16713 18354 18966 FLOPS/core
3
CPU:133 MHz 33679 36986 38220 FLOPS/core
4
CPU:266 MHz 67358 73973 76440 FLOPS/core
Also wie bei dir.
Direkt mal mit einer älteren 1.19.1 getestet:
Und schon passen die alten Werte.
Da scheinen die Buben eine üble Regression in der FP Arithmetik
eingebaut zu haben. Oder aus Versehen von float auf double gewechselt.
Muss ich mir anschauen.
PS. Danke für den Hinweis. Werde in der nächsten Woche gleich die FP
Arithmetik mit in den Testzyklus nehmen.
Norbert schrieb:> Also wie bei dir.
Danke, das beruhigt mich schonmal :)
Norbert schrieb:> PS. Danke für den Hinweis.
Gerne :) Ich hab ja auch etwas davon ;)
Nachtrag: Wirklich ein signifikanter Unterschied finde ich.
Eigentlich wollte ich ja mal diesen Test von dir hier nachvollziehen:
Beitrag "Re: PiPico Multicore"
Die Zahlen dort sind wirklich beeindruckend.
Ich hatte dir eine PM geschickt aber es kam leider keine Reaktion.
900ss schrieb:> Wirklich ein signifikanter Unterschied finde ich.
In der Tat. Das ist allein mit schlechterem Code nicht mehr zu erklären.
Ich vermutete ja float/double.
Aber gerade noch schnell getestet, das ist es definitiv nicht.
Sieht nach mehr Arbeit aus.
900ss schrieb:> Ich hatte dir eine PM geschickt aber es kam leider keine Reaktion.
Tut mir leid, die laufen mit größter Wahrscheinlichkeit nach /dev/null
Hat leider Foren(nutzer)gründe.
900ss schrieb:> Die Zahlen dort sind wirklich beeindruckend.
Ja, die Geschwindigkeit ist schon … ähm, angenehm. ;-)
Aber so etwas darf man hier auf gar keinen Fall laut sagen.
Harald K. schrieb:> Norbert schrieb:>> Aber so etwas darf man hier auf gar keinen Fall laut sagen.>> Wieso das?
Weil's nicht die "richtige" Programmiersprache für µC ist.
Das lassen ja eine nicht geringe Anzahl der hiesigen Forenteilnehmer
gerne bei jeder unpassenden Gelegenheit heraus hängen. Das man manche
Aufgaben noch nicht einmal in C schneller laufen lassen kann, macht's
nur noch schlimmer. Bequem und schnell, das kann und darf nicht sein.
Und nach einem knappen halben Jahrhundert Programmierung in mehr
Programmiersprachen als es einem gesunden Menschen gut tut, habe ich da
einfach keine Lust mehr drauf. Zumal es genügend internationale Foren
gibt, in denen sich die Teilnehmer erstaunlich zivilisiert verhalten.
Norbert schrieb:> Das lassen ja eine nicht geringe Anzahl der hiesigen Forenteilnehmer> gerne bei jeder unpassenden Gelegenheit heraus hängen.
Ich mag Python nicht besonders, da ich es für unübersichtlich halte,
aber damit gehe ich nicht hausieren, und erst recht nicht würde ich
anderen deswegen Vorhaltungen machen. Ich bin ja nicht der "C-Hater",
der seinen Programmiersprachenhass sogar zum Namen machte.
Aber wenn jemand mit Python Probleme lösen kann, warum nicht?
Norbert (der_norbert)
12.04.2025 21:24
>Weil's nicht die "richtige" Programmiersprache für µC ist.>Das lassen ja eine nicht geringe Anzahl der hiesigen Forenteilnehmer>gerne bei jeder unpassenden Gelegenheit heraus hängen.
Das musst du ignorieren. Es gibt immer Leute die nur das verwenden
wollen, was sie schon kennen. Und einige der Lautsprecher hier sind ja
ziemlich konservativ und haben Schwierigkeiten, sich auf Neues
einzustellen.
Das MC-Net hat über 10 Jahre gebraucht um halbwegs zu verstehen, was
"Arduino" nicht gleichbedeutend mit "keine Ahnung" ist und dass
"Einfachheit" auch im Professionellen Umfeld durchaus verwendet wird.
Hier der exemplarische Thread von 2013 (Arduino's gibt's seit ca. 2007):
Beitrag "Re: Arduino - bringt's das ?"
> Ich habe mir Micropython nach dem PDF "Raspberry Pi Pico-series Python> SDK" unter Linux installiert und die Runtime auf meinem Raspberry Pi> Pico (ohne W und auch nicht der 2) geflasht.> Nachtrag: Vielleicht liegt der Trick auch im compilieren vom Code.
Nach oberflächlicher Recherche in diversen Entwicklerforen könnte es
tatsächlich ein C-Problem (gcc) und kein Python-Problem sein.
Im Zusammenhang mit floating wird oft über die Nutzung/Verlinkung
schneller (fast) gcc routinen für Soft-float und des ROM geschrieben.
Vielleicht klärt man auch, wie man die fürs floating-Point nötigen
RAM-Tabellen flott zum Rechenwerk transferiert, resp. mit welchen
Compiler/linker-Option man dafür sorgt das der erzeugte Interpreter
flott auf alle nötigen Daten Zugreifen kann und nicht unnötig den Cache
überschreibt.
https://github.com/orgs/micropython/discussions/14437
Änderungen im float-teil gab es mit V1.22, vielleicht testet man mal im
Vergleich mit V1.21 .
Und gcc-Problem meint hier weniger einen Bug im Compiler als
Unterschiede in den Compiler/Linker-Command-Line-Options die im build
genutzt werden. Also weniger im C-Source stochern als in den
(c)make-files/Aufrufen.
> Wer also nördlich einer halben Million FLOPS pro Sekunde braucht…
... nimmt einen Prozessor mit integrierter Hardware-Floating-Point-Unit
wie den Pico 2 oder andere ...
Wobei man diese Menge floats erstmal aus den Sensoren saugen muß. Eher
untypisch für üblich Pico-Anwendungen.
Bradward B. schrieb:> ... nimmt einen Prozessor mit integrierter Hardware-Floating-Point-Unit> wie den Pico 2 oder andere ...
Schrieb ich in Zeile eins.
Pico 2 wird übrigens das Board genannt, RP235x ist der µC.
Norbert schrieb:> Mit dem RP2350
Wie gut das letzte Woche einer mit der Post kam. Er ist erstmal in die
Schublade gewandert aber nachher probiere ich den Test mal mit dem Teil.
Bin noch nicht betriebsbereit ;)
Bradward B. schrieb:> Eher untypisch für üblich Pico-Anwendungen.
Ist auch eher nicht dass Thema hier. Was sinnvoll oder üblich ist oder
auch nicht, bitte hier nicht diskutieren. Gibt nur Stress. ;)
Norbert schrieb:> Direkt mal mit einer älteren 1.19.1 getestet:
Auch gerade getestet damit habe ich auch Ergebnisse, die Deinen
entsprechen.
Norbert schrieb:> Mit dem RP2350:
Die Ergebnisse habe ich auch mit der V1.25 preview
Also in sofern bin ich jetzt beruhigt, es liegt hier kein Fehler vor.
Norbert schrieb:> Und nach einem knappen halben Jahrhundert Programmierung in mehr> Programmiersprachen als es einem gesunden Menschen gut tut, habe ich da> einfach keine Lust mehr drauf.
Da gehts mir ähnlich. Warum soll ich noch in Assembler programmieren,
wenn der kleine Pico ganz bequem und interaktiv mit Micropython
arbeitet. Und mit 6502 oder Z80 Assembler habe ich mich lange genug
gequält, ganz zu schweigen von MCS51 oder MCS48...
Matthias S. schrieb:> Da gehts mir ähnlich. Warum soll ich noch in Assembler programmieren,
Da habe ich mich missverständlich ausgedrückt.
Was ich meinte war: Ich habe keine Lust mehr auf diese zuvor en passant
erwähnten dümmlichen Diskussionen.
Scamp/65-/68- Assembler und noch einige mehr sind halt nun Thumb bzw.
RISC-V gewichen. Wenn's denn mal richtig pressiert.
Aber ich hab's nicht zu einer Religion erhoben, Basis ist eher gesunder
Pragmatismus.
Aus diesem Beitrag gelingt mir immerhin schon mal Fall 4 (Assembler,
asymmetrisches Signal):
Beitrag "Re: PiPico Multicore"
Allerdings hab ich an den Outputs wohl noch etwas falsch konfiguriert.
Ich schaue mir das Signal mit dem Scope an und messe nicht mit dem
anderen Core. Und das Signal ist eher ein verbogenes Dreieck-Signal.
Du schriebst ja, dass die Portpins das mitgehen können..... da muss ich
wohl noch etwas üben ;)
Aber das in Python so schnell zu bekommen, da bin ich auch noch nicht
soweit, da übe ich auch noch.
Edit: Wer misst misst Mist. :( Man sollte sein Scope auch richtig
einstellen. Der Bandbreitenfilter war eingeschaltet. Und die Masse ist
bei den Freqenzen auch nicht so unwichtig ;) Sieht schon besser aus.
900ss schrieb:> Aber das in Python so schnell zu bekommen, da bin ich auch noch nicht> soweit, da übe ich auch noch.
Hi Norbert, hast du bitte ein paar Stichwörter für mich? Ich bin
Anfänger in Python und ich fürchte da fehlt mir Wissen. Ich nehme nicht
an dass du eine Spezialität von Micropython nutzt. Vielleicht den
direkten Registerzugriff (toggle).
900ss schrieb:> Hi Norbert, hast du bitte ein paar Stichwörter für mich? Ich bin> Anfänger in Python und ich fürchte da fehlt mir Wissen. Ich nehme nicht> an dass du eine Spezialität von Micropython nutzt. Vielleicht den> direkten Registerzugriff (toggle).
Klar.
Zunächst, vergiss alles was mit der High Level Pin-Klasse zu tun hat. Da
hört's schon sehr früh auf Spaß zu machen. Vergleichbar mit der
Abstraktion der Abstraktion der Abstraktion eines GPIO bei Arduino. Für
LEDs (und Buttons) aber Klasse! ;-)
Also, der @micropython. viper decorator erlaubt dir eine
Beschleunigung um ein Vielfaches. Dafür migriert das (natürlich immer
noch Python) Erscheinungsbild ein wenig in Richtung C. Des weiteren
bekommt man direkte Registerzugriffe, in diesem speziellen Falle des
SIO. Dort findet man einen Mechanismus, welcher es gestattet mit einen
Befehl einen (oder mehrere) GPIOs zu setzen, zu löschen oder zu toggeln.
Viper ist deswegen der Champion, weil man mit einem Python Statement
ähnlich einem Pointer direkt auf eines dieser Register zugreifen kann.
In nahezu Assembler Geschwindigkeit.
Danke dir. Ok, den viper decorator habe ich benutzt (oder auch native)
aber da muss ich mich nochmal mehr schlau machen, wie man damit das
meiste herausholt.
Dass das über die Pin-Klasse nicht hinzubekommen ist in der
Geschwindigkeit, das leuchtet mir wohl ein. In Assembler habe ich direkt
auf die SIO (GPIO) Register geschrieben und dann "b( loop )".
"while true" scheint aber auch eine Schlafmütze zu sein.
900ss schrieb:> "while true" scheint aber auch eine Schlafmütze zu sein.
Bei Viper übersetzt »while 1:« direkt in den b(al) Befehl. Da wird's
schwer noch mehr Geschwindigkeit rauszuholen. ;-)
Sollte bei »while True:« aber eigentlich gleich sein.
Norbert schrieb:> Sollte bei »while True:« aber eigentlich gleich sein.
Ok, jetzt bin ich weiter, am Scope werden ~16.6MHz angezeigt. Vorher kam
ich über 280kHz nicht hinaus. Und ich nutze "while 1". Dein Testfall 1
ist erreicht :)
Unglaublich eigentlich. Mit einer Interpretersprache ohne eine Zeile
Assembler zu kodieren. Cool!
Jetzt frag ich mich noch, wie du den Testfall 2 hinbekommen hast. Ist ja
sogar schneller. wtf....
Edit: while True ist genauso schnell. War aber zu erwarten.
900ss schrieb:> Unglaublich eigentlich. Mit einer Interpretersprache ohne eine Zeile> Assembler zu kodieren. Cool!
Das ist ja das Gemeine! Wenn du eine Funktion in Viper schreibst, wird
ein Objekt daraus. Dieses Objekt wird zur Ladezeit automagisch in
Assembler kodiert. Man kann sich (mit ein wenig dunkler Magie) die
Binäre Repräsentation aus dem Objekt ziehen und als eine Sequenz von
Halfwords darstellen. Unter Zuhilfenahme des TR- und AR-Manuals kann man
das Zeug in Maschinensprache dekodieren.
Norbert schrieb:> Das ist ja das Gemeine! Wenn du eine Funktion in Viper schreibst, wird> ein Objekt daraus. Dieses Objekt wird zur Ladezeit automagisch in> Assembler kodiert.
Gibt's irgendwo etwas wo das genauer beschrieben steht?
900ss schrieb:> Gibt's irgendwo etwas wo das genauer beschrieben steht?
Tja, das ist die große Enttäuschung (war sie zumindest als ich begann)
Doku, almost nada. Also alles Handarbeit.
Könnte mittlerweile – eventuell – mit viel Glück – etwas besser sein.
Ganz sicher nicht bis zum Objekt auseinander pflücken und
disassemblieren. Aber zumindest eine sanfte Viper Einführung inklusive
all den Fallstricken.
Norbert schrieb:> Könnte mittlerweile – eventuell – mit viel Glück – etwas besser sein.
Ich stöbere nochmal. Bisher ist mir nicht unter gekommen.
Alle 4 Testfälle laufen jetzt :) Ist wirklich sehr beeindruckend!
Fehlt nur noch, dass man debuggen kann ;) Aber man könnte den Code evtl.
so schreiben, dass er auch auf dem PC läuft. Da kann man dann debuggen.
Danke für's Neugierde wecken und den Tips dazu :)
Edit: Falls du noch einen Tip hast, wie man die Kiste wieder anhält wenn
eine loop mit viper oder native läuft, dass wäre schön. Mir gelang
bisher nur Reset.
Edit2: das Anhalten wird wohl nur mit Reset funktionieren da sicher eine
Maschinencodeschleife läuft und da sonst nichts mehr dazwischen kommt.
900ss (900ss)
>Ich stöbere nochmal. Bisher ist mir nicht unter gekommen
Warum postest du nicht einfach die Codebeispiele? Dann kann man ja die
Fehler viel einfacher finden.
@Christoph Dein Zitat ist ein Mix aus echtem Zitat und eigenem Text. Das
ist schwer zu verstehen. Machst du aber oft so. Weshalb?
Nachtrag: Äh, sorry, das ist ein Fehler mit der Darstellung auf dem
Smartphone. Da wird das Zitat und dann dein geschriebene Text als Zitat
angezeigt. War mir bisher nicht aufgefallen. Vielleicht reicht eine
Leerzeile zwischen Zitat und dann eigenem Text.
Wenn du mein letztes Posting vollständig gelesen hättest (oder auch den
Thread), dann wüsstest du, daß es keine Fehler mehr gibt.
Mit den Hinweisen von Norbert hab ich alles lösen können.
Nachtrag: und ich wollte erstmal selbst graben und es selber zum Laufen
bringen damit ich gezwungen bin zu lernen. Erst wenn ich selbst wirklich
nicht mehr weiter gewusst hätte, dann würde ich schon den Code posten.
Hinweise oder Stichworte sind mir erstmal viel hilfreicher.
Matthias S. schrieb:> Habt ihr das jetzt schon mal mit einer PIO Routine verglichen?
Da ist für mich der Reiz nicht da. Dass die PIO das schafft, daran
besteht ja kein Zweifel. Aber Pythoncode, immerhin eine
Interpretersprache, der solch schnellen Code erzeugt, das ist schon sehr
beeindruckend.
Man muss natürlich schon sehen, das durch viper erzeugter Code nicht
überall möglich ist. Es funktioniert mit gewissen Konstrukten und
Datentypen. Aber trotzdem kann man bei entsprechendem SW Design enorme
Geschwindigkeiten bekommen. Wenn man dann noch die Möglichkeiten der HW
richtig nutzt, dann kann man sicher sehr vieles auch in Micropython
erledigen.
Ich hätte das nicht vermutet. Deshalb wollte ich das was Norbert im
anfangs velinkten Thread gezeigt hat, auch mal nachvollziehen. Mir lässt
es ein wenig die Kinnlade runter fallen ;)
>Matthias S. schrieb:>> Habt ihr das jetzt schon mal mit einer PIO Routine verglichen?
900ss (900ss)
14.04.2025 08:41
>Da ist für mich der Reiz nicht da. Dass die PIO das schafft, daran>besteht ja kein Zweifel. Aber Pythoncode, immerhin eine>Interpretersprache, der solch schnellen Code erzeugt, das ist schon sehr>beeindruckend.
Naja, mit Viper wird's ja eine Art Inline-Asssembler und verliert dann
auch viele der nützlichen Eigenschaften von Python (z.B. Float beim
PiPico).
Christoph M. schrieb:> verliert dann> auch viele der nützlichen Eigenschaften von Python (z.B. Float beim> PiPico).
Nein, nicht korrekt.
Float Operationen werden lediglich nicht beschleunigt.
Matthias S. schrieb:> Habt ihr das jetzt schon mal mit einer PIO Routine verglichen? Wenns ums> Pin toggeln geht, sollte man hier wohl ähnliche Ergebnisse bekommen,> oder?
Nein, mit PIO kann man ½×F_CPU erreichen. Weit außerhalb dessen, was man
mit Assembler zu erreichen vermag.
Norbert schrieb:> Nein, mit PIO kann man ½×F_CPU erreichen. Weit außerhalb dessen, was man> mit Assembler zu erreichen vermag.
Wie implementierst/entwickelst Du denn PIO-Abläufe unter Micropython?
Gibt es dort einen PIO-Assembler?
Vor einigen Jahren hatte ich mit µPython auf dem RP2040 herumgespielt,
es aber doch wieder liegen lassen.
Falls mal jemand Lust bekommt zu spielen, der Code im Anhang.
Bitte berücksichtigen, dass ich blutiger Anfänger in Python bin. Erst
recht in MicroPython. Bis vor 2 Tagen hatte ich noch nie etwas mit
gemacht.
Danke nochmal an Norbert für die Hilfe hier. Und für die Appetithäppchen
die hier im Forum verstreut sind ;)
900ss schrieb:> Bitte berücksichtigen, dass ich blutiger Anfänger in Python bin. Erst> recht in MicroPython.
Das vergiss mal schnell. Dein Code sieht schon verdammt gut aus.
Mi N. schrieb:> Wie implementierst/entwickelst Du denn PIO-Abläufe unter Micropython?> Gibt es dort einen PIO-Assembler?
Wurde ja zum teil schon beantwortet. Zusätzlich kann man ein
PIO-Programm während der Laufzeit programmatisch generieren und den
StateMachines verfügbar machen. Und zu guter Letzt ist es möglich
(ebenfalls während der Laufzeit) PIO-Programme aus dem Dateisystem zu
laden und nutzen.
Norbert schrieb:> 900ss schrieb:>> Bitte berücksichtigen, dass ich blutiger Anfänger in Python bin. Erst>> recht in MicroPython.>> Das vergiss mal schnell. Dein Code sieht schon verdammt gut aus.
Ich hab mir Mühe gegeben ;)
Es wäre nur nochmal interessant, woher die Laufzeitunterschiede zwischen
V1.19.1 und der aktuellen Version kommen, die ich im Eingangspost
beschrieben hatte.
Vielleicht sollte man mal einen Bugreport schreiben. Obwohl Bug ist es
ja nicht aber der Unterschied ist signifikant. Evtl. hat das ja auch
schon jemand erledigt. Hab nicht nachgesehen.
900ss schrieb:> Es wäre nur nochmal interessant, woher die Laufzeitunterschiede zwischen> V1.19.1 und der aktuellen Version kommen, die ich im Eingangspost> beschrieben hatte.
Es sieht wohl so aus als wären die SDK basierten FP-Ops in gewissen
Fällen nicht so präzise wie sie sein könnten. In nahezu allen
praktischen Fällen hat das zwar wohl noch nie zu Problemen geführt, aber
so wie ich das sehe ist nun ein anderes, langsameres jedoch präziseres
Modell eingeführt worden.
Da ich – außer bei den speziellen Testprogrammen — noch nie diese
Leistung gebraucht habe, ist es mir auch erst nach deinem frischen Test
aufgefallen.
Das ist OK (für mich) lieber höchstmögliche Präzision bei weniger Dampf.
(Man kann µPy übrigens auch für »double« kompilieren)
Zumal ich weiß, wo ich bei Bedarf knapp 800kFlops her bekommen kann. ;-)