Forum: Compiler & IDEs Hilfe bei Codeoptimierung


von Max T. (charmquark)


Lesenswert?

Hi zusammen,

ich habe für meinen 8x8x8 LED Würfel ein schönes Programm mit Bit Angle 
Modulation (JUHUU!!) geschrieben, allerdings machen mir manchen Zeilen 
Kummer, da sie >10 Zyklen brauchen.

Ausschnittsweise:
1
struct status
2
{
3
  uint8_t Row;      
4
  uint8_t Timeslice;  
5
  uint8_t Ticked;  
6
}
7
8
volatile uint8_t Matrix[8][8][8];  // [Row][Column][Timeslice]
9
volatile status Status;
10
11
void Irgendeine Funktion()
12
{ 
13
     PORTD = Matrix[Status.Row][1][Status.Timeslice];
14
}

Die Zeile scheint unendlich unvorteilhaft zu sein. Gibts da eine 
schnellere Möglichkeit?

von Ja (Gast)


Lesenswert?

Pointer

von Floh (Gast)


Lesenswert?

Max TBA schrieb:
> allerdings machen mir manchen Zeilen
> Kummer, da sie >10 Zyklen brauchen.

Und?
Gibts zeitliche Probleme? Hast du festgestellt, dass genau diese Zeile 
der Flaschenhals ist? Wastutdas restliche Programm?

Bedenke:
"Premature optimization is the root of all evil." :-)

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Ok, nehmen wir mal folgenden Code anstatt dem Text von oben, der zig 
Syntax-Fehler wirft:
 
1
#include <avr/io.h>
2
3
typedef struct
4
{
5
  uint8_t Row;      
6
  uint8_t Timeslice;  
7
  uint8_t Ticked;  
8
} status;
9
10
volatile uint8_t Matrix[8][8][8];  // [Row][Column][Timeslice]
11
volatile status Status;
12
13
void Irgendeine_Funktion()
14
{ 
15
     PORTD = Matrix[Status.Row][1][Status.Timeslice];
16
}
 
avr-gcc 4.6 mach daraus mit -mmcu=atmega8 -Os:
 
1
Irgendeine_Funktion:
2
  lds r30,Status
3
  ldi r31,lo8(0)
4
  lds r24,Status+1
5
  ldi r25,6
6
1:  lsl r30
7
  rol r31
8
  dec r25
9
  brne 1b
10
  subi r30,lo8(-(Matrix))
11
  sbci r31,hi8(-(Matrix))
12
  add r30,r24
13
  adc r31,__zero_reg__
14
  ldd r24,Z+8
15
  out 50-32,r24
16
  ret
  
avr-gcc 4.7 hingegen:
 
1
Irgendeine_Funktion:
2
  lds r30,Status
3
  lds r24,Status+1
4
  ldi r25,lo8(64)
5
  mul r30,r25
6
  movw r30,r0
7
  clr __zero_reg__
8
  subi r30,lo8(-(Matrix))
9
  sbci r31,hi8(-(Matrix))
10
  add r30,r24
11
  adc r31,__zero_reg__
12
  ldd r24,Z+8
13
  out 0x12,r24
14
  ret
 
Ergo: Nimm eine aktuelle Compiler-Version, denn Multiplikation ist 
billiger als ein Shift:

http://gcc.gnu.org/PR36467
http://gcc.gnu.org/PR49687

von Max T. (charmquark)


Lesenswert?

Ja, es gibt zeitliche Probleme dahingehend, dass ich BMP momentan nur 
(und schon knapp an der Grenze) mit 7 statt 8 Bit laufen lasse, und die 
USB-Implementation und -Datenübertragung noch vollkommen fehlt. Mal 
sehen, wie viel das noch in Anspruch nimmt.

Diese Zeile wird bei jedem Interrupt 8 mal (for Schleife über den 
mittleren Index) ausgeführt und braucht daher schon fast 250 Zyklen.

Wie macht man das mit einem Pointer schneller?

Schöne Grüße, Max

von Max T. (charmquark)


Lesenswert?

@gjlayde

Naja, es sind wie gesagt nur Ausschnitte, daher die Fehler. Ich kann 
leider kein ASM, deswegen verstehe ich nicht ganz was du mir sagten 
willst.

Ausserdem sehe ich gerade leider, dass ich wahrscheinlich im falschen 
Forum bin, da ich mit AVR Studio 6 arbeite. Sorry!

von Ja (Gast)


Lesenswert?

BAM würde ich sowieso in Assembler schreiben. Dann geht das auch locker 
mit 8bit. --> http://www.mikrocontroller.net/articles/AVR-Tutorial

Max TBA schrieb:
> Wie macht man das mit einem Pointer schneller?

Das versteht man am Besten wenn man AVR-Assembler kann und die Befehle 
des µC kennt. Die meisten Assembler-Befehle deiner Funktion werden 
gebraucht um die Speicheradresse deines Arrayindex' auszurechnen. Mit 
einem Pointer entfällt das.

Max TBA schrieb:
> Ausserdem sehe ich gerade leider, dass ich wahrscheinlich im falschen
> Forum bin, da ich mit AVR Studio 6 arbeite. Sorry!

Was glaubst mit welchem Compiler Atmel Studio 6 arbeitet?

von Max T. (charmquark)


Lesenswert?

Ja schrieb:
> BAM würde ich sowieso in Assembler schreiben.

Bringt das so viel Zeitersparnis, dass es sich lohnt dafür Assembler zu 
lernen?

Ich werde das mal mit Pointern versuchen und sehen wis läuft.

Danke schonmal für die Hilfe! =)

Max

von Oliver (Gast)


Lesenswert?

Ja schrieb:
> Die meisten Assembler-Befehle deiner Funktion werden
> gebraucht um die Speicheradresse deines Arrayindex' auszurechnen. Mit
> einem Pointer entfällt das.

Hm. Wie berechnest du den Pointer, und vor allem, warum sollte das dann 
weniger Assembler-Befehle benötigen?

Oliver

von Max T. (charmquark)


Lesenswert?

Ich habe mein 3D-Array so eingerichtet, dass ich den Pointer auf den 
ersten Wert setze, und dann bei jedem Zugriff nur den Pointer eins 
weiterschiebe und auf dem gewünschten Wert lande. Ich muss dabei nur ein 
einziges mal, nach jedem vollständigen Zyklus über alle 8x8x8 Werte den 
Zeiger auf einen diskreten Wert, das erste Element im Array, setzen. 
Klappt jedenfalls ganz gut. Muss aber heute abend nochmal genauer 
testen.

Grüße,
Max

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.