Forum: Mikrocontroller und Digitale Elektronik Optimierung verstehen


von AVR Beginner (Gast)


Lesenswert?

Hallo,
bin Anfänger auf dem Gebiet, also haut mich nicht gleich.

Ich hab das Problem, dass GCC mir das weg optimiert:
1
U08 msg_new[msgSize];
2
U08 i;
3
  
4
uint8_t address = msg[0];
5
6
for(i=0; i<msgSize; i++)
7
{
8
  msg_new[i] = msg[i+1];
9
}

Optimierung steht auf: -O0
Wenn ich die Optimierung ausschalte geht es.
Aber warum wird es weg optimiert?
Und wie kann ich es verhindern, ohne komplett die Optimierung 
ausschalten zu müssen.

Danke

von Wolfgang (Gast)


Lesenswert?

AVR Beginner schrieb im Beitrag #5326652:
> Aber warum wird es weg optimiert?

Weil es nicht gebraucht wird oder der Compiler das nicht weiss.
Wo und wie ist msg[] deklariert?
Wie sieht dein wahrer, vollständiger Minimal-Code aus, bei dem dein 
Problem auftritt?
Was genau ist überhaupt dein Problem?

von Flo (Gast)


Lesenswert?

Ich spekulier mal: msg_new[] wird nie gelesen.
Ansonsten posten bitte ein komplettes Codebeispiel, wo das Verhalten 
auftritt.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

AVR Beginner schrieb im Beitrag #5326652:
> Optimierung steht auf: -O0
> Wenn ich die Optimierung ausschalte geht es.

Kaum zu glauben. Bist Du sicher mit dem O0?

Auszug aus:

https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html

-O0

    Reduce compilation time and make debugging produce the expected
    results. This is the default.

von Einer K. (Gast)


Lesenswert?

Bahnhof!

Warum verwendest du nicht memcpy() ?

von AVR Beginner (Gast)


Lesenswert?

Wolfgang schrieb:
> Wo und wie ist msg[] deklariert?

Sorry vergessen:
1
unsigned char msg[msgSize];
Wolfgang schrieb:
> Weil es nicht gebraucht wird

Ich will es aber haben.

Wolfgang schrieb:
> Wie sieht dein wahrer, vollständiger Minimal-Code aus, bei dem dein
> Problem auftritt?

Verstehe nicht ganz.
Ich will ein Array um eins nach links verschieben.
Geht das auch einfacher?

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

AVR Beginner schrieb im Beitrag #5326672:
> Ich will ein Array um eins nach links verschieben.

Ein und dasselbe Array?

Warum benutzt Du dann 2 verschiedene Arrays?

> msg_new[i] = msg[i+1];

von AVR Beginner (Gast)


Lesenswert?

Arduino F. schrieb:
> Warum verwendest du nicht memcpy() ?

Kenn ich nicht.
Wenn das einfacher ist, dann nehme ich das. Muss mich aber erst 
einlesen.

Frank M. schrieb:
> Bist Du sicher mit dem O0?

Entschuldigung:
Natürlich Quatsch. Es ist -O1.
Hab mich vertan, da ich schon zu viel daran herumgespielt habe.

von Einer K. (Gast)


Lesenswert?

AVR Beginner schrieb im Beitrag #5326672:
> Geht das auch einfacher?
 memcpy()

Und noch einfacher: Darauf verzichten, und stattdessen einen Ringbuffer 
verwenden.

von AVR Beginner (Gast)


Lesenswert?

Frank M. schrieb:
> Warum benutzt Du dann 2 verschiedene Arrays?

Stimmt, ich könnte es auch im selben machen, danke.

von Thomas M. (langhaarrocker)


Lesenswert?

Deine Schleife geht bis i<msgSize.
In der Schleife greifst Du aber lesend noch auf msg[i+1] zu, also ein 
Element "hinter" Deinem msg Array. Das ist nicht definiert. Da es aber 
nur lesend ist, dürfte dabei nichts schlimmeres passieren, als dass Du 
einen Quatsch-Wert erhältst. Das sollte aber mit Deiner eigentlichen 
Fragestellung nichts zu tun haben.

von AVR Beginner (Gast)


Lesenswert?

AVR Beginner schrieb im Beitrag #5326678:
> Frank M. schrieb:
>> Warum benutzt Du dann 2 verschiedene Arrays?
>
> Stimmt, ich könnte es auch im selben machen, danke.

Habs mal mit einem Array gemacht, wird auch weg optimiert, warum?
Lasst mich nicht dumm sterben.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

AVR Beginner schrieb im Beitrag #5326688:
> Habs mal mit einem Array gemacht, wird auch weg optimiert, warum?

Glaube ich nicht, aber mit ein- und demselben Array hast Du dann einen 
Fehler:
1
U08 msg[msgSize];
2
3
for(i=0; i<msgSize; i++)
4
{
5
  msg[i] = msg[i+1];
6
}

Wenn beim letzten Schleifendurchlauf i = msgSize - 1 ist, dann greift 
msg[i+1] ins Klo.

Richtig wäre:
1
U08 msg_new[msgSize];
2
3
for(i = 0; i < msgSize - 1; i++)    // Eins weniger kopieren!
4
{
5
  msg[i] = msg[i + 1];
6
}

Was soll dann mit dem letzten Member von msg passieren? Auf 0 setzen?

von AVR Beginner (Gast)


Lesenswert?

Arduino F. schrieb:
> Und noch einfacher: Darauf verzichten, und stattdessen einen Ringbuffer
> verwenden.

Wie meinst du das? Was wird dann einfacher?

von Purzel H. (hacky)


Lesenswert?

> wird auch weg optimiert, warum?

Weils nichts bringt. Ein paar Werte verschieben bringt nichts. Der 
Compiler merkt dass es nichts bringt. Die Welt dreht weiter wenn die 
Operation fehlt.

Du kannst die Variable als "volatile" definieren. Dann bleibt sie.

von Wolfgang (Gast)


Lesenswert?

AVR Beginner schrieb im Beitrag #5326672:
> Wolfgang schrieb:
>> Weil es nicht gebraucht wird
>
> Ich will es aber haben.

Dann musst du es auch verwenden. Sonst wird es wegoptimiert.

von AVR Beginner (Gast)


Lesenswert?

Frank M. schrieb:
> Wenn beim letzten Schleifendurchlauf i = msgSize - 1 ist, dann greift
> msg[i+1] ins Klo.
>
> Richtig wäre:
> U08 msg_new[msgSize];
>
> for(i = 0; i < msgSize - 1; i++)    // Eins weniger kopieren!
> {
>   msg[i] = msg[i + 1];
> }

Aber bei i=msgSize wird doch die Schleife gar nicht mehr ausgeführt, 
oder ist das falsch?

von AVR Beginner (Gast)


Lesenswert?

Wolfgang schrieb:
> Dann musst du es auch verwenden. Sonst wird es wegoptimiert.

Ich arbeite später doch mit den Variablen weiter. Reicht das nicht?

von Einer K. (Gast)


Lesenswert?

AVR Beginner schrieb im Beitrag #5326688:
> Habs mal mit einem Array gemacht, wird auch weg optimiert, warum?

Meine Glaskugel sagt:
Die Veränderung passiert in einer ISR.
Aber die Variablen sind nicht volatile.

Also:
Da wird nichts weg optimiert.


// ---------

Meine Glaskugel sagt:

Das ist sowieso der erste Gedanke, der auf den Müll gehört!
> wegoptimiert

Der Compiler optimiert nichts wichtiges weg.
Never.
Vielleicht gibts Probleme mit (kaputtoptimierten) Zeitschleifen, aber 
nicht mit der Funktion/Logik.

Der Fehler liegt woanders.

von AVR Beginner (Gast)


Lesenswert?

Zwölf M. schrieb:
> Du kannst die Variable als "volatile" definieren. Dann bleibt sie.

Ok. Ich probier es.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

AVR Beginner schrieb im Beitrag #5326708:
> Aber bei i=msgSize wird doch die Schleife gar nicht mehr ausgeführt,
> oder ist das falsch?

Korrekt, aber bei i = msgSize - 1 wird sie noch ausgeführt und
1
msg[i+1] identisch mit msg[msgSize - 1 + 1] identisch mit msg[msgSize]

ist dann nicht mehr definiert, denn Dein Array geht nur von 0 bis 
msgSize - 1.

Konkret: Von 100 Werten kannst Du nur 99 nach links schieben.

von Thomas M. (langhaarrocker)


Lesenswert?

Array Indizes beginnen bei 0.
Definierst Du ein Array mit 10 Elementen:
int myArray[10];

Dann hat das nur die Einträge mit Index 0..9

myArray[0] // gültig, erstes Element
myArray[9] // gültig, zehntes Element
myArray[10] // nicht gülitig, wäre ja das elfte Element

von Jim M. (turboj)


Lesenswert?

Arduino F. schrieb:
> Warum verwendest du nicht memcpy() ?

Weil das hier ein Fall memmove() ist.

AVR Beginner schrieb im Beitrag #5326708:
> Aber bei i=msgSize wird doch die Schleife gar nicht mehr ausgeführt,
> oder ist das falsch?

Blöd nur das der letzte valide Index von msg[msgsize] halt msgsize-1 
ist. Off-by-one, ein sehr beliebter Programmierfehler.

von AVR Beginner (Gast)


Lesenswert?

Frank M. schrieb:
> AVR Beginner schrieb im Beitrag #5326708:
>> Aber bei i=msgSize wird doch die Schleife gar nicht mehr ausgeführt,
>> oder ist das falsch?
>
> Korrekt, aber bei i = msgSize - 1 wird sie noch ausgeführt undmsg[i+1]
> identisch mit msg[msgSize - 1 + 1] identisch mit msg[msgSize]
>
> ist dann nicht mehr definiert, denn Dein Array geht nur von 0 bis
> msgSize - 1.

Hast recht. hat aber keine Auswirkung auf die Optimierung.

von Wolfgang (Gast)


Lesenswert?

AVR Beginner schrieb im Beitrag #5326710:
> Ich arbeite später doch mit den Variablen weiter.

Bist du sicher, dass das die selbe Variable ist?
Der Compiler optimiert die Variable nicht weg, wenn er sieht, dass du 
drauf zugreifst.

Wie sieht dein Code wirklich aus?

von AVR Beginner (Gast)


Lesenswert?

Kann ich dem Compiler nicht irgendwie sagen, dass er den Codeteil nicht 
weg optimieren soll?

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

AVR Beginner schrieb im Beitrag #5326721:
> Kann ich dem Compiler nicht irgendwie sagen, dass er den Codeteil nicht
> weg optimieren soll?

Wie gesagt: Ich glaube es nicht, dass der Code wegoptimiert wird - 
jedenfalls dann, wenn Du ein- und dasselbe Array verwendest und Du 
danach noch drauf zugreifst.

Zeige den kompletten Source und zeige genau die Stelle, an der Du 
angeblich merkst, dass der Code wegoptimiert ist! So ist das ein 
Stochern im Dunkeln!

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Jim M. schrieb:
> Weil das hier ein Fall memmove() ist.

memmove auf einem µC ist suboptimal. Aus dem Manual:
1
The memmove() function copies n bytes from memory area src to memory area dest. The memory areas may overlap: copying takes place as though the bytes in src are first copied into a temporary array that does not overlap src or dest, and the bytes are then copied from the temporary array to dest.

Das per malloc() allokierte Array willst Du auf einem µC nicht.

von AVR Beginner (Gast)


Lesenswert?

Frank M. schrieb:
> Zeige den kompletten Source und zeige genau die Stelle, an der Du
> angeblich merkst, dass der Code wegoptimiert ist! So ist das ein
> Stochern im Dunkeln!
1
void TWI_Start_Transceiver_With_Data( unsigned char *msg, unsigned char msgSize)
2
{  
3
  U08 i;
4
    
5
  uint8_t address = msg[0];
6
7
  for(i=0; i<msgSize-1; i++)
8
  {
9
    msg[i] = msg[i+1];
10
  }
11
12
  TWI_MasterWrite(&twiMaster, address, msg , msgSize-1);
13
}

[Mod: C-Formatierung eingebaut]

von Ralf (Gast)


Lesenswert?

Warum das ganze hin und her kopieren?

Es kam schon mal der Vorschlag : Ringbuffer!

Prüfe mal ob das was für dich wäre. Wenn du nicht weißt was das ist - 
Insternetsuche.

https://de.wikipedia.org/wiki/Warteschlange_(Datenstruktur)

von Tom (Gast)


Lesenswert?

AVR Beginner schrieb im Beitrag #5326733:
1
unsigned char msgSize;
2
 U08 i;
3
 for(i=0; i<msgSize-1; i++)

Preisfrage: Was passiert hier bei msgSize == 0?

von Einer K. (Gast)


Lesenswert?

Jim M. schrieb:
> Weil das hier ein Fall memmove() ist.

Bitte bemerke:
Anfangs war von 2 Arrays die Rede.

Wenn sich zwischendurch der Kontext ändert, solltest du das nicht mir 
ankreiden.


Aber da schon memcpy() nicht bekannt war, glaube ich dass der Bock ganz 
woanders zu suchen ist.
Den da liegt noch viel mehr im Nebel.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Ralf schrieb:
> Es kam schon mal der Vorschlag : Ringbuffer!

Ringbuffer wäre hier absoluter Blödsinn, an msg[0] steht der Wert von 
address - ganz einfach.

An den TO: Du brauchst den Buffer überhaupt nicht nach links kopieren. 
Für Deine Anforderung kannst Du das viel einfacher erledigen:
1
void TWI_Start_Transceiver_With_Data( unsigned char *msg, unsigned char msgSize)
2
{  
3
    TWI_MasterWrite(&twiMaster, msg[0], msg + 1,  msgSize - 1);
4
}

Dein Vorhaben reduziert sich also auf einen Einzeiler. Hier wird einfach 
ein Pointer ab der Stelle msg + 1 übergeben.

P.S.
Formatiere bitte zukünftig Deinen Code hier mit
1
[c] code [/c]

Dann wird das lesbarer. Ich habe das oben mal für Dich gemacht.

von AVR Beginner (Gast)


Lesenswert?

Frank M. schrieb:
> void TWI_Start_Transceiver_With_Data( unsigned char *msg, unsigned char
> msgSize)
> {
>     TWI_MasterWrite(&twiMaster, msg[0], msg + 1,  msgSize - 1);
> }

Hallo.
Habs probiert.
Da geht gar nichts.

Danke

von Michael R. (mr-action)


Lesenswert?

Dann liegt dein Fehler wo anders und durch das Einschalten der 
Optimierung killst du wo anders das Verhalten deines Codes...

von AVR Beginner (Gast)


Lesenswert?

Michael R. schrieb:
> ann liegt dein Fehler wo anders und durch das Einschalten der
> Optimierung killst du wo anders das Verhalten deines Codes...

Wenn ich den Debugger anschließe, dann sagt er mir aber genau in dieser 
for-Schleife "optimized away".
Dann gibt es doch dort ein Problem, oder nicht?
An dieser I2C Schnittstelle hängt ein Display. Es zeigt Zeichen an, wenn 
die Optimierung aus ist. Sobald ich eine einschalte geht es nicht mehr.

Wie kann ich es heraus finden, wo es noch sonst noch hakt?

von Gu. F. (mitleser)


Lesenswert?

AVR Beginner schrieb im Beitrag #5330212:
> Wie kann ich es heraus finden, wo es noch sonst noch hakt?

Indem du nicht länger nur Codefetzen postest, sondern ein LAUFFÄHIGES 
Programm, mit dem jeder dein Problem nachvollziehen kann.
Anders kann dir keiner helfen.

von Einer K. (Gast)


Lesenswert?

AVR Beginner schrieb im Beitrag #5330212:
> Dann gibt es doch dort ein Problem, oder nicht?

Nicht unbedingt.
Du siehst da nur die Handgranate hoch gehen.

Die Wirkung.
Die Ursache ist woanders.

Tipp:
> Der Weg in die Hölle ist mit falschen Annahmen gepflastert.

von Jan K. (jan_k)


Lesenswert?

Poste das gesamte Beispiel. Was heißt da geht nix? Die Leute hier waren 
echt hilfsbereit, aber jetzt muss mal was von dir kommen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.