Archiv verlassen und diese Seite im Standarddesign anzeigen : Warum: Vermeide Bit-Variablen! ??
Hallo,
habe im RN-Wiki den Artikel über BASCOM gelesen.
Dort steht bei Tips und Tricks: Vermeide Bit-Variablen!
WARUM ??
Ich benutze oft Bitvariablen als Flag für verschiedene Ereignisse.
Was ist daran schlecht? Bis jetzt hat's immer funktioniert...
Über eine Erklärung würde ich mich freuen.
MfG,
Andreas
Ich würde sagen, dass der Grund hierfür der ist, dass ein Controller mindestens 8Bit Speicherplatz für eine Variable belegt, egal ob es sich um eine Bit-Variable oder eine Byte-Variable handelt. Daher ist eine Bit-Variable ineffektiv, da 7 Bits ungenutzt bleiben. Besser wäre es also, mehrere Flags in eine Variable zu packen und bei Verwendung zu maskieren. Dadurch wird der Code zwar schwerer lesbar, aber man spart ein paar Bytes an RAM.
askazo
Bluesmash
15.10.2007, 15:17
mann könnte ja auch die einzelnen bits der byte variable mit alias namen versehen, dann könnte man wieder "direkt" darauf zugreifen....
gruss bluesmash
vielleicht ist es ja auch bloß eine glaubensfrage...wie die zulässigkeit vom goto befehl in basicprogrammen....
Hallo,
danke erst mal für die Infos. Das mit der Einsparung klingt logisch. Aber bei einem Mega32 oder gar Mega128 ein paar Byte einsparen.... naja...
Die Sache mit den Goto-Befehlen ist mir allerdings genauso schleierhaft...
dl1akp
Die Sache mit den Goto-Befehlen ist mir allerdings genauso schleierhaft...
Vergiss einfach die Antwort von dremler. Er liefert immer wieder solche Antworte. Mal abgesehen davon, dass es beim Goto-Befehl in BASCOM noch keine Probleme gab und man diesen Befehl fast nie verwendet...
jon
wenn man ein Bit deklariert geht zwar schon ein komplettes Byte dafür drauf allerdings belegt BASCOM das nächste deklarierte Bit mit der gleichen Speicherzelle bis die 8 Bits "voll" sind! - so habe ich das jedenfalls mal aus dem Protokoll nach dem compilen rauslesen können!
warum man das also vermeiden sollte ist mir auch nicht weiter bekannt.
Das Problem mit Bit's is weniger der Platz als der Prog-Code.
Bits tauscht er immer über das T-Bit aus, das gibt z.B für das einfache Statement
BIT.5 = 1
eine ganze Menge Maschinen Befehle
War schon öfter die Rede davon, ich werd' wohl einmal ein Demo in die Wiki stellen
MeckPommER
16.10.2007, 09:08
Es ist hier ja auch nicht die Rede davon, das man etwas vermeiden sollte, weil es sonst nicht funktioniert, sondern weil es vorteilhafter ist, dieses und jenes zu vermeiden.
Einzelne Bits zu setzen ist zu vermeiden, da - wie PicNick schon schrieb - Bascom dies recht umständlich realisiert, was größeren und langsameren Code erzeugt.
Ein "goto" zu vermeiden ist eigentlich eher eine Frage der Eleganz und Lesbarkeit. Wer seine Programmstruktur mit vielen "goto"s versieht, der wird recht schnell nicht mehr durchsehen vor lauter Sprüngen und Sprungzielen. Die meisten Programmabläufe lassen sich gestalten ohne ein goto zu verwenden und werden dadurch, quasi als Nebeneffekt, eleganter, leichter lesbar und ab und zu auch schneller.
Nochmal: funktionieren kann auch das heftigste Spaghettiprogramm mit hunderten von goto-Befehlen.
@PicNick: deinen diesbezüglichen Wiki-Eintrag werde ich sicherlich auch mit größtem Interresse lesen. Marvin freu sich über jede Optimierung :)
Eine Frage drängt sich mit aber gleich auf. Wie sieht es mit den Ports aus, ist das setzen einzelner Bits dort auch so langsam? (Müßte ja eigentlich, oder?)
Und ists besser, die Ports immer als Byte komplett zu setzen anstatt einzelne Bits?
<weitergrübel>
Dann müßte man sich ja am besten eine Byte-Variable einrichten, deren Bits mit AND und OR gesetzt bzw. gelöscht werden und die dann komplett an den Port übergeben wird.
Oder macht dieses Verfahren mehr umstand als es verbesserugn bringt?
</weitergrübel>
Den Bascom-Code zu optimieren ist ein Thema, zu dem es bisher noch meiner Meinung nach viel zu wenige Infos gibt. Ich bin gespannt, was da noch kommt!
Gruß MeckPommER
Ich hab' da noch ein paar Beispiele hinzugefügt. Vielleicht will wer gucken.
Abgefeimte Assembler-Fuzzies bekommen da natürlich Tränen in die Augen, aber wat is, det is.
https://www.roboternetz.de/wissen/index.php/Bascom_Inside-Code#BITVARIABLE
stefan_Z
16.10.2007, 14:14
noch ein kleiner off-topic-Hinweis zu GOTO:
Mit GOTO 0 kann man in Bacom den µC reseten, ist manchmal auch nicht verkehrt.
hmm ich muss das nu noch mal ausgraben-.....weil ichs eben erst gesehen hab..
Vergiss einfach die Antwort von dremler. Er liefert immer wieder solche Antworte. Mal abgesehen davon, dass es beim Goto-Befehl in BASCOM noch keine Probleme gab und man diesen Befehl fast nie verwendet...
@jon:
woher nimmst du deine weisheiten?? das ich städig sowas schreiben würde?? außerdem gibt es auch leute die dieser befehl sehr wohl und auch oft verwenden.....also bist du es wohl der hier sachen schreibt die man vergessen sollte.....
Den Bascom-Code zu optimieren ist ein Thema, zu dem es bisher noch meiner Meinung nach viel zu wenige Infos gibt. Ich bin gespannt, was da noch kommt!
Welche Möglichkeiten gibt es denn überhaupt den Erfolg irgendwelcher Optimierungsversuche festzustellen?
Beim Compilieren zeigt der Compiler an, wieviel Speicher das Programm belegt. Das ist zwar ein Anhaltspunkt, da aber nur angegeben wird wieviel Prozent des Speichers das gesamte Programm belegt, ist es für kleinere Optimierungen in einem grüsseren Programm nicht besonders genau.
Mit AVR Studio kann man den von Bascom compilierten Code durch den Disassembler jagen. Wenn man Assembler versteht, kann man dann natürlich sehen, was Bascom da zusammengebastelt hat.
Wenn man - wie ich - kein Assembler versteht, kann man höchstens die Zeilen zählen. Wenn man das nach jeder kleineren Änderung macht um den Erfolg festzustellen, ist das aber auch recht mühsam.
Wiwviel Speicvher das gesamte Programm belegt oder wieviel Zeilen Assemblercode Bascom daraus macht ist ja auch oft gar nicht so wichtig.
Intreressanter ist es oft bei einzelnen Routinen die häufig, oder sogar per Interrupt aufgerufen werden.
Welche Möglichkeiten gibt es denn da, festzustellen was Bascom daraus macht.
Oder anders gefragt, wie kann ich feststellen wieviel Takte der Controller z.B. für meine Interrupt-Routine benötigt, und ob der Optimierungsversuch überhaupt ewas gebracht hat?
Hallo,
...kann man höchstens die Zeilen zählen
Assemblerzeilen zählen bringt nur wenig.
Ausser wenn es nur um den Flash-Verbrauch geht.
Wenn es um die Geschwindigkeit geht,
ist oft ist der längere Code sogar der schnellere.
Stichwort: Ausrollen von Schleifen
Gruß Jan
MeckPommER
05.11.2007, 13:28
@JanB jupp, das Ausrollen kleinerer schleifen kann sinnvoll sein, ebenso zu nennen wären vielleicht noch:
- überprüfen ob dinge doppelt oder unnütz berechnet werden
- überprüfen, ob funktionen oder werte nicht als tabelle im speicher vorab abgelegt werden können
- möglichst subs oder funktionen vermeiden, sondern gosub verwenden
Eine Möglichkeit, die Erfolge von Optimierungen zu überprüfen ist, am Anfang des betreffenden Codes einen Counter zu starten und diesem an Ende des Codes auszulesen.
@dremler: sicherlich funktioniert der goto-Befehl absolut zuverlässig, aber ich habe bisher noch keinen Programmcode mit vielen gotos gesehen, den man nicht viel eleganter und besser lesbar ohne 95% der gotos hinbekommen kann.
Ein gutes Listing/Programm kommt deshalb ohne viele gotos aus. Ich hab mal nachgeschaut - in meinem Programm für Marvin gibt es maximal 1 oder 2 gotos, und das bei mehr als 10.000 Programmzeilen. Mit vielen Sprüngen wäre das Lesen und Verstehen so eines Codes wohl auch kaum noch möglich.
Gruß MeckPommER
Wenn man ASM gewohnt ist, dann benutzt man vllt. auch in BASCOM Gotos... ich hab in BASCOM diesen Befehl zwar auch noch nicht verwendet, aber jedem das seine. Man sollte hier nicht verallgemeinern. Die einen hassen, was die anderen lieben.
MeckPommER
05.11.2007, 15:21
In ASM kommt man ja ums Springen nicht herum, wenn auch die meisten Sprünge bedingte Sprünge sind, deren Basic-"Gehaltsequivalent" ich eher in einem "IF" als einem "Goto" sehe.
Klar, jeder kann natürlich programmieren, wie ihm/ihr beliebt. Man kann seine Suppe auch mit einer Gabel löffeln, sollte aber nicht versuchen, andere von den Vorzügen zu überzeugen ;-)
Assemblerzeilen zählen bringt nur wenig.
Ausser wenn es nur um den Flash-Verbrauch geht.
Das ist mir eigentlich klar, daher habe ich ja gefragt, wie man bei einzelnen Routinen feststellen kann wie schnell (in wieviel Takten) diese ausgeführt werden.
- überprüfen ob dinge doppelt oder unnütz berechnet werden
Die Gefahr ist bei einem grösseren Programm sicherlich gegeben.
Dass man das selber prüfen muss und die Entscheidung welche Programmteile unnütz sind nicht irgendeinem Tool oder dem Compiler überlässt, finde ich aber eigentlich ganz OK ;-)
- überprüfen, ob funktionen oder werte nicht als tabelle im speicher vorab abgelegt werden können
Das wird vermutlich erst ab einer gewissen "Komplexität" der Funktionen Vorteile bringen und wenn ich da richtig liege, ist es halt hilfreich, wenn man den Erfolg auch prüfen kann.
- möglichst subs oder funktionen vermeiden, sondern gosub verwenden
OK, das ist mir neu. Kommt mir aber entgegen, da ich eigentlich immer zu faul war Subs und Funktionen zu nutzen und mir das erst in diversen Codeschnipseln und Beispielprogrammen abgeguckt habe.
Eine Möglichkeit, die Erfolge von Optimierungen zu überprüfen ist, am Anfang des betreffenden Codes einen Counter zu starten und diesem an Ende des Codes auszulesen.
Ich habe es mal über nen Zähler in einer Interrupt-Routine versucht, dabei aber irgendwie so rumgemurkst, dass nichts sinnvolles dabei rauskam.
Einen Counter zu verwenden ist ein guter Plan ;-)
Reicht es, wenn man das im Simulator macht oder pfuscht da das seltsame Verhalten von Windows rein?
Um die Takte über einen Counter zu zählen sollte ja eigentlich der Simulator reichen und das Multitasking von Windows keine Rolle spielen.
slavezero
06.11.2007, 19:55
mein Dank an PicNick - sehr schön die Bsp.
mir kommen die Tränen bei der PortPin abfrage.
tschüß sc
Hallo! Auf der Googlesuche nach dem genauen Effekt von "Goto 0" bin ich auf diesem Thread gestoßen...
Hier lese ich:
- möglichst subs oder funktionen vermeiden, sondern gosub verwenden
Bevor ich mir nun die Mühe mache meinen ganzen Code umzustellen um den Effekt zu testen - ist diese Meinung noch aktuell und begründet?
Meine zweite Frage bleibt: Hat goto 0 den gleichen Effekt wie ein Hardware Reset?
Meine zweite Frage bleibt: Hat goto 0 den gleichen Effekt wie ein Hardware Reset?
Nicht ganz. Das Programm wird wieder vom Startpunkt aus ausgeführt, aber die Hardware wird nicht neu initalisiert. Alle Register behalten die alten Werte.
Einen wirklichen Reset kann man nur mit dem Watchdogtimer auslösen.
peterfido
05.04.2009, 12:57
Nein, denn die Variablen und Register behalten ihre Werte und ein evtl vorhandener Bootloader wird nicht angesprungen. Die Pegel an den Ausgängen ändern sich auch nicht.
Du springst einfach nur an den Anfang des Programmes zurück. Einen Reset löse ich mit Hilfe des Watchdogs oder einer externen Beschaltung aus.
edit: Zu lange mit der Antwort gewartet.....
okay, danke für die Hinweise. Dann werde ich mich mal über den Watchdog informieren. Hat noch jemand einen Tipp zu meiner ersten Frage? Gosub oder sub? Was ist "besser"?
MeckPommER
05.04.2009, 13:09
Gosub mit globalen Variablen ist schneller, da bei Funktionen und Sub die Werte umständlicher übergeben werden. Macht sich aber nur bemerkbar bei zeitkritischen Sachen oder sehr häufigen Aufrufen.
Gruß MeckPommER
Hi Meckpommer!
Macht sich aber nur bemerkbar bei zeitkritischen Sachen oder sehr häufigen Aufrufen.
Ich denke diese Voraussetzungen erfüllt mein Tricopter... 7 Subs die alle mit ca. 350 Hz aufgerufen werden (eben so schnell wie möglich). Dann teste ich das mal und schreibe hier meine Erfahrungen nieder.
MeckPommER
05.04.2009, 13:19
Jo, das müßte sich schon bemerkbar machen.
Bin gespannt auf deine Ergebnisse!
Gruß MeckPommER
Ich habs eben ausprobiert. Unter den gegebenen Umständen kann ich bei meiner Anwendung keinen Unterschied feststellen. Beide Varianten laufen gleich schnell.
Der Reset per Watchdogtimer klappt prima!
thewulf00
06.04.2009, 08:48
Es gibt einen Unterschied zwischen Software-Reset und Hardware-Reset, genau wie uwe schon sagte, sind einige Initialisierungen dann hinfällig. Es gibt andere, bessere Methoden. Die geeignetste ist wohl die Watchdog-Methode, genau wie Uwe sagte.
Mehrere Threads dazu gibt es hier im Forum, auch aus philosophischer Sicht.
Wer aus dem Assembler-Bereich kommt, für den stellt ein Software-Reset nicht wirklich einen Reset dar. (Allein aus dem Grunde, dass lediglich Sachen ausgeführt werden, die man auch selber machen könnte.)
MeckPommER
06.04.2009, 13:42
@ Willa,
ich habe bei der Umstellung von Funktionen und Prozeduren geringe aber deutliche Unterschiede feststellen können. Die Frage ist natürlich, wie dein Programm konkret aussieht.
Je mehr Parameter übergeben wurden, desto deutlicher ist der Unterschied. Wenn nun (um Prozeduren und Funktionen zu vermeiden) diese Parameter jedes mal vor dem Aufruf in andere Variablen geschaufelt werden, damit es zum Code in den Funktionen bzw. Prozeduren passt, dann ist der positive Effekt fast schon wieder komplett aufgebraucht.
Mal "grob ins Blaue" gefaselt kannst du bei der Gosub-Variante vielleicht 2-4 Takte sparen + 4 Takte je Parameter + noch ein paar je lokal dimensionierter Variable.
Ob es sich lohnt, ist natürlich immer abhängig von deinem Programm. Bei der Programmierung des Beinsystems für meinen Bot war es extrem wichtig, bei deinem coolen Kopter macht es vielleicht nur einen unmerkbaren Unterschied von 0.1%.
Subs und Funktionen können jedenfalls die Lesbarkeit eines Programms erheblich verbessern, weswegen ich niemals generell auf reine GOSUBs umstellen würde.
Was nützt einem das schnellste Programm, wenn man nachher vor lauter GOSUBs nichts mehr editieren kann ;-)
Gruß MeckPommER
Am meinsten verbraucht man, wenn man "Byval" angeben (muss).
Dann ist Bascom nämlich gezwungen, die Variable in das "Frame" zu kopieren, und das kostet nun wirklich.
Bei "Byref" wird nur die Adresse der Variablen auf den (Soft)Stack gelegt.
python_rocks
06.04.2009, 19:48
Subs und Funktionen können jedenfalls die Lesbarkeit eines Programms erheblich verbessern, weswegen ich niemals generell auf reine GOSUBs umstellen würde. Was nützt einem das schnellste Programm, wenn man nachher vor lauter GOSUBs nichts mehr editieren kann ;-)
Hallo!
+1
Da bin ich voll deiner Meinung. Optimieren sollte man erst dann, wenn es einen Grund zum Optimieren gibt. Und bis es soweit ist, hat man mit Prozeduren und Funktionen ordentlich strukturierten Code in der Hand, der sich leicht warten lässt.
Auch auf BYVAL sollte man erst verzichten, wenn es denn unbedingt notwendig ist. Denn ein BYVAL hat schon viele Programmierer vor Fehlern bewahrt. Wenn irgendwo in einer Funktion oder Prozedur eine globale Variable verändert wird, dann werden größere Programme ziemlich schnell unübersichtlich.
Übergebe die Daten die die Funktion braucht an die Funktion und gib die geänderten Daten zurück. Achte darauf, Funktionen und Prozeduren so zu gestalten, dass diese unabhängig von der Umgebung sinnvoll arbeiten können. Dann haben Funktionen und Prozeduren ihren Zweck erfüllt: Eine Aufteilung eines komplexen Gesamtprogrammes in kleine, weniger komplexe Teilprogramme.
mfg
Gerold
:-)
PS: Das soll nicht heißen, dass man nicht optimieren soll. Wenn man mehr Leistung braucht, dann ist es gut zu wissen, was man am Code verändern kann um vorhandene Leistungsengpässe zu umgehen. Man soll nur nicht von Anfang an die Ausführgeschwindigkeit optimieren. Erst recht nicht, wenn noch nicht sicher ist, ob es überhaupt einen Grund dafür gibt.
.
Keine Ahnung warum bei mir kein deutlicher Performance unterschied erkennbar ist... Ich habe Subs eigentlich sowieso nur verwendet um mein Programm in Kapitel zu unterteilen. Es werden auch maximal 8 Variablen - verteilt auf zwei word-arrays - zwischen den insgesamt 6 Subs übergeben. Einige Subs kümmern sich auch gar nicht um die anderen Subs und machen ihr eigenes Ding. Ist vielleicht noch nicht komplex genug für einen Performance Unterschied. Dabei ist mein Mega32 immerhin bis zur Hälfte gefüllt ;-)
Gerade bei Arrays gilt PicNicks Hinweis auf den Frame in besonderem Maße.
Mit Byref wird nur ein Pointer auf den Stack gelegt, mit Byval muss jedes Element des Arrays umkopiert werden
Aber ansonsten gebe ich Gerold schon recht.
Gruß
Rolf
man kann sich aber auch kaputtoptimieren ....
wenn ich mir da verschiedene meiner Listings anschau,
da ohne SUB oder FUNCTION zu werken würd mich doch
z.T. mächtig beschränken.
Kritisch ist halt da die Verwendung lokaler Variablen, das
bremst mächtig, ist aber schön komfortabel wenn man
Prozeduren in ne externe Datei auslagert und die dann bei
verschiedenen Programmen gemeinschaftlich nutzt ...
Aber das sind Philosophiefragen, da gibts kein schwarz oder weiß,
da gibts unzählige Grauabstufungen dazwischen
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.