2015-07-03 9 views
5

Ich habe fast DES-Algorithmus mit C-Sprache implementiert, und ich möchte meinen Code optimieren. Also habe ich gprof benutzt. Hier ist ein Teil des Berichts:48-Bit-Folge von acht 6-Bit-Einheiten: Wie bekomme ich die mittleren 4 Bits jeder Einheit schnell

Each sample counts as 0.01 seconds. 
    % cumulative self    self  total   
time seconds seconds calls us/call us/call name  
51.78  9.32  9.32 8000000  1.17  1.17 sboxes 
34.71  15.57  6.25 8000000  0.78  0.78 extendRight 
    9.90  17.35  1.78 500000  3.56 35.96 operation 
    2.39  17.78  0.43 8000000  0.05  0.05 xorRightAndKey 

gprof zeigt, dass sboxes Funktion 51,78% der Zeit besetzt.

In sboxes(uchar aucData[6], ...) wurde ich 48 Bits gegeben, spaltete sie in 8 Schlitz, wobei jeder Schlitz von 6 Bit.

für jeden Slot:

  1. ersten Bit mit dem letzten Bit kombiniert X zu erhalten;

  2. Mitte 4 Bit erhalten Y zu erhalten;

  3. etwas mit (X, Y);

Zum Beispiel 011110 ist ein Schlitz, so X = 00 und Y = 1111.

Um dies zu implementieren, ich MACRO schrieb im Speicher GET/SET-Bit, ist hier relativ Code:

#define LOCATE(ptr, index) (((char *)(ptr))[(index) >> 3]) 

#define GET_BIT(ptr, index) (LOCATE((ptr), (index)) & (((uchar)0x80) >> ((index) % 8))) 

Und hier ist der Code (X, Y)

uchar basePos = 0x00; 
for (int i = 0; i < 8; ++i) { 
    x = 0; 
    y = 0; 
    basePos = i * 6; // to locate the slot 
    // combine first bit with last bit 
    if (0 != GET_BIT(aucData, basePos)) { 
     x |= 0x02; 
    } 
    if (0 != GET_BIT(aucData, basePos + 5)) { 
     x |= 0x01; 
    } 
    // get continuous 4 bits 
    for (int j = 1; j <= 4; ++j) { 
     if (0 != GET_BIT(aucData, basePos + j)) { 
      y |= (0x01 << (4 - j)); 
     } 
    } 
    // do something with (x, y) 
} 

Also meine Frage zu bekommen, ist , Ich bekam 48 Bits, wie bekomme ich die mittleren 4 Bits so schnell wie möglich?

+3

Wenn jeder 6 Bits ist, können Sie eine Nachschlagetabelle erstellen? – Robinson

+0

Wählen Sie eine: C oder C++. – fuz

+1

Sie können wahrscheinlich separat optimierte Routinen für eine Sequenz schreiben, die mehrere Bytes umfasst, und für eine Sequenz, die dies nicht tut. Dies würde die aktuelle Bit-für-Bit-Vorgehensweise vermeiden. – usr2564301

Antwort

4

Ohne Lookup-Tabelle:

typedef unsigned long long u64; 

void sboxes(uchar aucData[6]) 
{ 
    u64 v = aucData[0] + (((u64)aucData[1]) << 8) 
    + (((u64)aucData[2]) << 16) 
    + (((u64)aucData[3]) << 24) 
    + (((u64)aucData[4]) << 32) 
    + (((u64)aucData[5]) << 40); 

    for(int i = 0; i < 8; i++) 
    { 
     uchar x = ((v & 1) << 1) | ((v >> 5) & 1); 
     uchar y = ((v >> 1) & 0xF); 
     // do something with x, y 
     printf("x: %hhu, y: %hhu\n", x, y); 

     v >>= 6; 
    } 
} 

vollständiger Haftungsausschluss: Ich habe nicht an einer Benchmark. Aber es sollte schnell sein. Sie können das Packen in u64 schneller machen, wenn es immer noch zu langsam ist.

+0

Zuerst Ihr Code funktioniert nicht, ich habe versucht, es zu beheben, aber vergeblich. Zum Beispiel erhielt ich 16 Bits '00001111 00001111', ich muss die Byte-Reihenfolge berücksichtigen. –

+0

Wie funktioniert es nicht? Ich habe es getestet, bevor ich es eingereicht habe. Es sei denn, ich habe die Frage falsch verstanden. Wenn ein Slot Bits ABCDEF hat, dann X = FA, Y = BCDE, richtig? Es sei denn, Sie sagen, dass der Inhalt des Eingabearrays nicht in Ordnung ist (d. H.die richtige Reihenfolge ist _nicht_ aucData [0] -> aucData [1] -> aucData [2] -> ...) – tohoho

+0

X = AF, Entschuldigung für meine Ausdrucksfähigkeit. Wenn wir 'uchar aucData [6] = {0xfc, 0x11, 0x22, 0x33, 0x44, 0x55} '' erhalten, dann wäre 'v'' 0x000055443322113fc', nach 'v >> = 6' die rechten 6 Bits von '0xfc' ist verschwunden, aber die linken 6 Bits von '0xfc' sind der erste Slot. –