Forum: Mikrocontroller und Digitale Elektronik Bits aus Byte-Array extrahieren Alg.


von lepper03 (Gast)


Lesenswert?

Hallo zusammen,

ich habe eine Frage bzgl. Algorithmus zum Zerschneiden vom Array. Ich 
habe ein Byte-Array und soll aus dem Array bestimmte Informationen 
rauslesen. Die Informationen sind in dem Byte Array grupiert und ich 
kenne das StartBit und die Länge in Bits. Die extrahierte Bytes/Bits 
soll ich in ein anderes Byte-Array hinkopieren (dsa für die extrahierte 
Länge passt).

Was ist der beste (schnell und optimiert) Algorithmus Eure Meinung nach, 
um diese Aufgabe zu erledigen?

Danke im Voraus für die Antworten

von Ralf G. (ralg)


Lesenswert?

lepper03 schrieb:
> Was ist der beste (schnell und optimiert) Algorithmus Eure Meinung nach,
> um diese Aufgabe zu erledigen?

Was hast du denn bist jetzt für einen 'schlechten' Algorithmus? Da kann 
man bestimmt darauf aufbauen. (Des besseren Verständnisses wegen.)

von lepper03 (Gast)


Lesenswert?

eben bis jetzt fällt mir nichts vernünftiges ein ;(

habe so gedacht:

startbyte = startbit / 8
startBit  = startbit % 8
endbyte = (startbit + length) / 8
endBit  = (startbit + length) % 8

und dann die grenzeden Byte(s) (start/end) bearbeiten/extrahieren und 
die dazwischen liegende einfach kopieren. Eigentlich, das ist 
Randproblem.

Die Rand-Byte(s) müsste ich mit Shift-Operationen 
rausholen.....hmmmm....Ws meint Ihr?

von Tuner (Gast)


Lesenswert?

Also ohne weitere Informationen wirst du wohl jedes Bit anfassen müssen 
und schauen ob es ein Startbit ist. Bei dieser Ausgangslage vom ersten 
bis zum (letzten-Wortlänge).

Schneller geht es wenn du dein System kennst.
- Kommt das Startbit nur am Anfang eines Bytes (Nur noch jedes 8. Bit 
anfassen) [Wobei sich mir da beim drüber nachdenken gerade die Frage 
aufdrängt wie in einem digitalen System ein StartBIT aussieht]
- Ist es wahrscheinlicher dass es später kommt als direkt am Anfang 
(Startwert der Suche)
- Gibt es andere Muster? Kommt eventuell immer etwas identisches davor?
...

grüße

von lepper03 (Gast)


Lesenswert?

mehr Informationen würden mir nicht weiterhelfen. StartBit und Länge 
sind schon ausreichend.

Hier ein Beispiel:

Byte myArray[256]

Gruppe1: StartBit: 0, Länge 20 Bits
Gruppe2: StartBit: 20, Länge 50 Bits
Gruppe3: StartBit: 70, Länge: 100 Bits
....
etc....

von Mark B. (markbrandis)


Lesenswert?

lepper03 schrieb:
> Die extrahierte Bytes/Bits soll ich in ein anderes Byte-Array hinkopieren
> (dsa für die extrahierte Länge passt).

Kann es ja ohnehin nicht, wenn die Gesamtlänge an "Nutzbits" nicht durch 
8 teilbar ist.

D.h. wer auch immer die Daten weiterverarbeitet, wird auch wieder darauf 
schauen müssen und braucht die Zusatzinformation, wieviele Bits denn 
genutzt werden sollen.

> Was ist der beste (schnell und optimiert) Algorithmus Eure Meinung nach,
> um diese Aufgabe zu erledigen?

Ich wüsste nicht, was man da viel optimieren kann. Zumal es vorrangig 
auf die Korrektheit der Ergebnisse ankommt.

Wenn es gerade mal um 256 Bytes geht, die insgesamt zu verarbeiten sind, 
dann dürfte damit so ziemlich jeder Mikrocontroller fix fertig sein. Es 
sei denn die Aufgabe muss Millionen Male pro Sekunde durchgeführt 
werden.

: Bearbeitet durch User
von Carsten P. (r2pi)


Lesenswert?

@OP:

Ohne semantische Zusatzinformationen kann man da konkret kaum was zu 
sagen, wie ein schneller Algorithmus aussehen kann / soll.

Mark Brandis direkt über mir hat schon darauf hingewiesen, dass selbst 
ein verschlafener ATtiny 25 über ein paar paarhundert Bits nur 
schmunzeln würde.

Wenn Du hingegen einen riesigen Datenberg durchzuschaufeln hast, geht 
es, wie auch andere schon geschrieben haben, um Muster, Bedeutung -- 
also Semantik. Wenn die Informationsblöcke immer gleich lang sind und 
nicht 2^(8n) lang sind, also keine n Bytes, sondern irgendwas krummes, 
von mir aus 777 Bits, könnte es allgemein je nach verfügbarem RAM sogar 
angebracht sein, in Assembler oder Low-Level-C über den Speicher zu 
rumpeln, ein Byte/Word/DWord etc. auszulesen, den Inhalt zu kopieren, 
mit Shift-Operationen das Paket rauszuholen (mitlaufender Zähler) und 
aus jedem Bit ein neues Byte(!) zu machen.

Warum? Damit Du danach in einer "vernünftigen" Sprache Deiner Wahl 
(Java(script), C#, Python...) den Verarbeitungsprozess pro Datenblock 
(die angenommenen 777 Bits) auf vielen, vielen Prozessorkernen parallel 
ablaufen lassen kannst. Hier reden wir dann aber schon über echt große 
Datenmengen, die schnell abgearbeitet werden müssen, also von 
irgendeiner Hardware vom Raspi 3 an aufwärts bis zu einem 
ausgewachsenen, massiv-parallelen Cluster. Und sowas ist sogar in C++ 
schon eine ausgesprochen hässliche Angelegenheit, geschweige denn in C 
oder ASM. Als alter "Microsoftie" würde ich das ganze in der 
DotNet-Umgebung laufen lassen (Mono), weil man dort ein echtes 
Schlaraffenland in Sachen Thread-Verwaltung findet, aber ähnliche 
Bibliotheken gibt es bestimmt auch für Java und andere neuere Sprachen.

von lepper03 (Gast)


Lesenswert?

Ok, die "Nutzbits" müssen nicht unbedingt durch 8 teilbar ist. Die 
unbenützte Bits wird man reseten. Die Bytes kommen via CAN-Bus als 
Botschaften. Die Botschaften beinhalten Signale, welche zu Signalgruppen 
zusmmengefasst werden können: 
https://www.autosar.org/fileadmin/files/releases/4-2/software-architecture/communication-stack/standard/AUTOSAR_SWS_COM.pdf

von optimierer (Gast)


Lesenswert?

Je nachdem wie schlecht dein Compiler ist kann man bei den Divisionen 
und Modulo Operationen schon optimieren --> Shift Operator und logisches 
AND (&).
Das bring aber nur etwas, wenn diese Operationen vergleichsweise oft 
aufgerufen werden, z.B. die Länge der zu extrahierenden Daten kurz ist.
Division und Modulo auf einem Microcontroller ohne Divisions-Einheit 
brauchen da schon mal xx Befehle, um das umzusetzen... einen schlechten 
Compiler vorausgesetzt.

Außerdem könnte man auch Sonderfälle (z.B. Startbit ist durch 8 Teilbar) 
gesondert optimieren.

Wie immer hängt aber die optimale Umsetzung von der Zielplattform ab... 
i7, ARM Cortex, Attiny?? Linux/Windows/C/C++/C#/Java ...

Und die wichtigste Frage ist, ob dieser Algorithmus überhaupt optimiert 
werden muss, oder ob deine Performance eh ganz wo anders verloren geht 
;)

von lepper03 (Gast)


Lesenswert?

Es geht um ANSI C und TC1797(Infineon)

von optimierer (Gast)


Lesenswert?

Und du bist du sicher, dass dieser Algorithmus optimiert werden muss?
Bei CAN-Baudraten bis 1Mbps und max. 8 Bytes pro Nachricht wird deinem 
Controller eh langweilig ;)

von lepper03 (Gast)


Lesenswert?

na ja, wir haben jetzt schon 70% CPU auslastung, dort müssen kritische 
Funktionen berechnet werden. Meine Funktionen sind vielleicht 1% von dem 
ganzen und das Alg. ein sehr kleines Teil von der Funktion, was sagen 
wir 200 mal alle 5 msec aufgerufen wird ;)

von lepper03 (Gast)


Lesenswert?

ich habe nicht nur CAN aber auch Flexray, CANFD und Ethernet ;)

von Peter M. (r2d3)


Lesenswert?

lepper03 schrieb:
> die dazwischen liegende einfach kopieren. Eigentlich, das ist

Und was machst Du, wenn Du ein Byte, bestehend aus 8 Bit von 
Quellposition 0 an Zielposition 1 kopieren sollst?

Dann kannst Du das Byte nicht einfach kopieren.

Lauf durch die Quellbits und kopiere sie einzeln.
Vielleicht reicht Dir die Geschwindigkeit schon.

Geschwindigkeit gewinnen durch das Kopieren von ganzen Bytes kannst Du 
nur dann, wenn Quellposition und Zielposition bei der Division durch 8 
mit Rest im Rest übereinstimmen.

Anstelle über Optimierungen zu sinnen, solltest Du einfach den naiven 
Kopieralorithmus, bzw. die primitive Bitkopierschleife realisieren.

Die Experten hier haben dann bestimmt noch Ideen, wie sich der 
Kopiervorgang des einzelnen Bits beschleunigen lässt.

: Bearbeitet durch User
von lepper03 (Gast)


Lesenswert?

Zielposition ist eigentlich einfach, Quellposition 0 an Zielposition 0 
usw.
d.h.
Byte myArray[256]

Gruppe1: StartBit: 0, Länge 20 Bits
Gruppe2: StartBit: 20, Länge 50 Bits
Gruppe3: StartBit: 70, Länge: 100 Bits

Gruppe1 wird einfach an ZielArray1 geschrieben:
ZielArray1[0] = StartBit: 0, Länge 8 Bits
ZielArray1[1] = StartBit: 8, Länge 8 Bits
ZielArray1[2] = StartBit: 16, Länge 4 Bits
....

ok, danke Euch, ich werde mir es jetzt am WE überlegen und mein Ergebnis 
hier posten.

von Peter M. (r2d3)


Lesenswert?

Achtung:

An welcher Position im Ziel landet denn Startbit 20?
Bei Bitposition Null oder anderswo?

von lepper03 (Gast)


Lesenswert?

@Peter M: Startbit 20 gehört schon zur neuen Gruppe d.h. neues Array => 
an der Stelle 0.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

lepper03 schrieb:
> ok, danke Euch, ich werde mir es jetzt am WE überlegen und mein Ergebnis
> hier posten.

 Die anderen Verfahren mögen zwar in C Programm schöner und kürzer
 aussehen aber Bitschifterei ist immer die schnellste Art.

von lepper03 (Gast)


Lesenswert?

Mir fällt nichts vernünftiges ein, alles scheint hoch kompliziert zu 
sein :( jemand hat über BitCopyLoop geschrieben, aber wird immer 
kompliziert da man ständig berechnen muss wann neues Byte/Bit im 
QuelleArray endet und wann das neue Byte/Bit im ZielArray anfängt bzw. 
wenn im ZielArray Platz vorhanden ist muss genutzt werden.

Was ich noch machen kann, anstatt es dynamisch zu berechnen, einfach den 
Code zu generieren und im Vorfeld d.h. im Generator schon einige 
Berechnugen vorzubereiten...

Am Anfang habe ich mir gedacht, dass es nicht so schwierig sein kann...

von Mark B. (markbrandis)


Lesenswert?

lepper03 schrieb:
> Mir fällt nichts vernünftiges ein, alles scheint hoch kompliziert zu
> sein :(

Was ist hoch kompliziert? Das was Du hier beschrieben hast:

> startbyte = startbit / 8
> startBit  = startbit % 8
> endbyte = (startbit + length) / 8
> endBit  = (startbit + length) % 8

klingt doch nach einem Ansatz der funktionieren kann, wenn man ihn 
richtig ausprogrammiert.

Ansonsten gilt wie immer:
Teile das zu lösende Problem in kleinere Teilprobleme auf.

von Peter M. (r2d3)


Lesenswert?

lepper03 schrieb:
> und dann die grenzeden Byte(s) (start/end) bearbeiten/extrahieren und
> die dazwischen liegende einfach kopieren. Eigentlich, das ist
> Randproblem.

Das geht nur in Spezialfällen und klappt im Allgemeinen nicht.

Quelle: Startbit Nr. 4 (die 1!)
Länge: 16

0000 1011   0011 1110 1111

Dann muss das Ziel so aussehen:

1011 0011   1110 1111

Wie Du siehst, kannst Du das das zweite Byte nicht einfach kopieren.

=> Probiere den naiven Algorithmus: Bit für Bit kopieren, also
"Bit einlesen, Bit schreiben"

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

lepper03 schrieb:
> Es geht um ANSI C und TC1797(Infineon)

Der hat doch genug RAM, nimm einfach uint8_t oder bool pro bit und nutze 
normale Arrays.

von lepper03 (Gast)


Lesenswert?

Danke Euch allen, Ich werde den Code (zumindes diesen Anteil) doch 
spezifisch generieren.

von Carsten P. (r2pi)


Lesenswert?

Fa bin ich ganz bei dir. Wir sind nicht mehr in den Zeiten von 
Mycro-Supra-Nenno-Prozessoren, die nur 64 Bytes zur Verfügung haben. 
Nicht umsonst übersetzt die GCC in der Regel bool in int.

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.