PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Optimierung von Funktion



shedepe
04.11.2010, 17:39
Ich habe folgende Funktion:


inline uint8_t CreateChecksum()
{

uint8_t CheckSum = 0;


for(int j = 1; j <4; j++)
{

for(int i = 0; i < 8; i++)
{
int bit = (uartbuffer[j] & (1<<i)) >> i;
if(bit ==1)
{
CheckSum += (uint8_t)(1 * i);
}

}

}
return CheckSum;
}

Diese Funktion berechnet eine Checksumme aus 3 Arrayfelder, aus meinem uartbuffer. Die Checksumme wird über den Uart zurückgesendet um zu überprüfungen ob die Daten korrekt übertragen wurden.
Dabei wird für jedes Bit das 1 ist die Schleifenvariable zur Checksumme dazu addiert.

Kann man das ganze eventuell noch optimieren ?

radbruch
04.11.2010, 18:14
Hallo

Ich denke, der klassische Ansatz ist hier XOR:

inline uint8_t CreateChecksum()
{
uint8_t CheckSum = 0;

for(int j = 1; j <4; j++)
{
CheckSum ^= uartbuffer[j];
}
return CheckSum;
}


Ob das so funktioniert habe ich allerdings nicht getestet. Die zu prüfenden Bytes werden einzeln mit XOR verknüpft, fehlende oder zuviele Bits werden erkannt.

Gruß

mic

BMS
04.11.2010, 18:15
Für die Variablen in den for-Schleifen kannst du kleinere Datentypen verwenden. Also anstatt int eben nur einen unsigned int mit 8 Bit (uint_8t). Ebenso mit "int bit=...". Die Variable bit kannst dir auch schenken, wenn du gleich if(uartbuffer[]...usw...) schreibst.
Wenns wirklich zeitkritisch ist, dann würde ich die innere Zählschleife weglassen und den Inhalt 8x nacheinander hinschreiben.

TobiKa
04.11.2010, 18:21
Die Variable CheckSum kannst du dir auch sparen, indem du die Variable in die der Wert von CheckSum kommen soll, per Pointer übergibst.

SprinterSB
04.11.2010, 22:42
Die Frage ist, *was* du optimieren willst: Laufzeit? Speicherverbrauch? Fehlererkennungsrate? Verständlichkeit? Portierbarkeit? ...

Abhängig davon, und abhängig vom verwendeten Compiler und dessen Beschalterung, der verwendeten Hardware, der Definition von uartbuffer[] und dem konkreten Kontext, in den das Codestück schliesslich geinlinet wird, wird die Antwort anders ausfallen.

rossir
04.11.2010, 23:39
Man kann z.B. die Resultate Deiner for-i-Schleife vorab (offline) berechnen und in einem const uint8_t Array (der Größe 256) ablegen und dann etwa so benutzen:


inline uint8_t CreateChecksum()
{

uint8_t CheckSum = 0;


for(int j = 1; j <4; j++)
{
CheckSum += vorab[uartbuffer[j]];
}
return CheckSum;
}

shedepe
05.11.2010, 12:31
@SprinterSB
Ich hatte bei Optimieren erst mal nur an die Laufzeit gedacht. Aber deine Frage ist natürlich vollkommen richtig und es ist mir erst nach dem schreiben meines Posts aufgefallen, dass man auch noch andere Sachen Optimieren kann.

SprinterSB
05.11.2010, 17:32
In diesem Falle hängt es auch von der verwendeten Architektur ab. Es gibt architekturen, da kostet ein Sprung oder ein Speicherzugriff zu viel wie 20 arithmetische Instruktionen. Wenn's ein Cache gibt, fällt der Overhead nur beim ersten Lesen an. Dito für Sprünge wenn's eine Jump Prediction (Sprungvorhersage) gibt.

Dann stellt sich auch die Frage, ob die Optimierung wirklich norwendig ist, weil anderswo Zeitrahmen nicht eingehalten werden können, zB weil die Funktion innerhalb einer ISR zur Ausführung kommt oder in "normalem Code". Weiters hängt es davon ab, wieviel Speicher man für Konstanten opfern möchte, gesett den Fall auf der Harware ist ein Table-Lookup schneller als Arithmetik. Wenn kein Speicher verfügbar ist oder zu knapp, bringt es nix, sich zu überlegen, ob man Zeit gegen Platz tauschen möchte.