2010-12-12 12 views
3

Im beginnend mit einem Array von 100.000 Bytes, wo nur die unteren 6 Bits in jedem Byte nützliche Daten haben. Ich muss diese Daten so schnell wie möglich in ein Array von 75.000 Bytes packen, wobei die Reihenfolge der Daten erhalten bleibt. Packen von Daten in Arrays so schnell wie möglich

unsigned int Joinbits(unsigned int in) {} 
+3

6 Bits * 4 = 24 Bits = 3 Bytes. Schreiben Sie Code, um mit vier Bytes gleichzeitig umzugehen, und machen Sie mit jedem das Richtige, und Sie sind auf einem Gewinner. –

+0

Was ist Ihre Systemwortgröße? Was ist Ihr Systemprozessor? "So schnell wie möglich" hängt vom systemspezifischen Verhalten ab, z. B. welche Operationen die meiste Parallelität und die geringste Menge an Code zur Folge haben. –

+0

Vorausgesetzt, dass einige Ihrer 6-Bit-Werte Byte-Grenzen im Ergebnis überlappen, kommt hier die Endianess zum Tragen. Welchen Endian willst du? –

Antwort

4
// 00111111 00111111 00111111 00111111 
// 000000 001111 111122 222222 
void pack6(
    register unsigned char o, 
    register unsigned char const *i, 
    unsigned char const *end 
) 
{ 
    while(i!=end) 
    { 
    *o++ = *i   << 2u | *(i+1) >> 4u; ++i; 
    *o++ = (*i & 0xfu) << 4u | *(i+1) >> 2u; ++i; 
    *o++ = (*i & 0xfcu) << 6u | *(i+1)  ; i+=2; 
    } 
} 

fehl, wenn Eingabelänge ist nicht teilbar durch 4 hoch 2 Bits von Eingangs Geht davon sind gleich Null. Vollständig portabel. Liest 4 Eingabebytes 6 Mal, also 50% Ineffizienz bei Lesevorgängen, jedoch können der Prozessorcache und der Compileroptimierer helfen. Der Versuch, eine Variable zu verwenden, um das Lesen zu speichern, kann kontraproduktiv sein, nur eine tatsächliche Messung kann dies erkennen.

0
for(int pos=0; pos<100000; pos+=4) 
{ 
    *(int*)out = (in[0] & 0x3F) | ((in[1] & 0x3F)<<6) | ((in[2] & 0x3F)<<12) | ((in[3] & 0x3F)<<18); 
    in += 4; 
    out += 3; 
} 
+0

Das funktioniert nur auf Plattformen, auf denen int mit irgendeiner Ausrichtung sein kann. –

+0

Wird auf den meisten Plattformen aufgrund von Fehlausrichtung segfault. – Yttrill

+1

Die meisten Plattformen? Sicher meinst du einige Plattformen. Wenn Sie Windows als Plattform zählen. – TonyK

0

Dies ist C, ich weiß nicht C++ kennen. Und ist wahrscheinlich mit Bugs gefüllt, und ist auf keinen Fall der schnellste Weg, es ist wahrscheinlich nicht einmal schnell. Aber ich wollte es einfach ausprobieren, denn es schien eine lustige Herausforderung zu sein, etwas zu lernen, also triff mich bitte mit dem, was ich falsch gemacht habe! : D

unsigned char unpacked[100000]; 
unsigned int packed[75000/4]; 

for (int i = 0; i < (100000/6); i += 6) { 
    unsigned int fourBytes = unpacked[i]; 
    fourBytes += unpacked[i + 1] << 6; 
    fourBytes += unpacked[i + 2] << 12; 
    fourBytes += unpacked[i + 3] << 18; 
    fourBytes += unpacked[i + 4] << 24; 
    fourBytes += unpacked[i + 5] << 30; 

    unsigned short twoBytes = unpacked[i + 5] >> 2; 
    twoBytes += unpacked[i + 6] << 4 
    twoBytes += unpacked[i + 7] << 10; 

    packed[i] = fourBytes; 
    packed[i + 4] = twoBytes; 
} 
+0

Zunächst sollten Sie unsigned chars und ints ausschließlich für Bit-Manipulationen verwenden. Und Ihre zwei letzten Zuweisungen funktionieren nicht, sie weisen nur Bytes an Position i und i + 4 zu. – Yttrill

+0

Auch verlieren Sie die letzten vier Bytes von entpackten []. – TonyK

+0

Sie möchten 4 Eingangsbytes in 3 Ausgangsbytes packen. Sie packen gerade 5 in 4 und versuchen dann 3 in 2 zu packen, wo sie nicht passen. Auch das Zuweisen eines int zu einem char-Array füllt nicht 4 aufeinanderfolgende Array-Slots mit den int-Daten (selbst wenn angenommen wird, dass "sizeof (int) == 4" in C OR C++ nicht garantiert ist). Er konvertiert das int in ein char und weist es dem angegebenen Slot zu. –

Verwandte Themen