Sembra che questo codice è di circa 50 orologi per bit di swap sul mio i7 XPS 8500 della macchina. 7,6 secondi per un milione di lanci di schiera. Filettato singolo. Stampa alcune opere ASCI basate su pattern di 1 e 0. Ho ruotato la foto a sinistra di 180 gradi dopo aver invertito l'array di bit, utilizzando un editor grafico, e sembrano identici a me. Un'immagine a doppia inversione è la stessa dell'originale.
Per quanto riguarda i vantaggi, è una soluzione completa. Scambia i bit dalla parte posteriore di un array di bit alla parte anteriore, operando su interi/byte e quindi scambiando ints/byte in una matrice.
Inoltre, questa è una libreria di bit generica, quindi potrebbe essere utile in futuro per risolvere altri problemi più banali.
È veloce come la risposta accettata? Penso che sia vicino, ma senza un codice funzionante per il benchmark è impossibile dirlo. Sentiti libero di tagliare e incollare questo programma di lavoro.
// Reverse BitsInBuff.cpp : Defines the entry point for the console application.
#include "stdafx.h"
#include "time.h"
#include "memory.h"
//
// Manifest constants
#define uchar unsigned char
#define BUFF_BYTES 510 //400 supports a display of 80x40 bits
#define DW 80 // Display Width
// ----------------------------------------------------------------------------
uchar mask_set[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
uchar mask_clr[] = { 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f };
//
// Function Prototypes
static void PrintIntBits(long x, int bits);
void BitSet(uchar * BitArray, unsigned long BitNumber);
void BitClr(uchar * BitArray, unsigned long BitNumber);
void BitTog(uchar * BitArray, unsigned long BitNumber);
uchar BitGet(uchar * BitArray, unsigned long BitNumber);
void BitPut(uchar * BitArray, unsigned long BitNumber, uchar value);
//
uchar *ReverseBitsInArray(uchar *Buff, int BitKnt);
static void PrintIntBits(long x, int bits);
// -----------------------------------------------------------------------------
// Reverse the bit ordering in an array
uchar *ReverseBitsInArray(uchar *Buff, int BitKnt) {
unsigned long front=0, back = BitKnt-1;
uchar temp;
while(front<back) {
temp = BitGet(Buff, front); // copy front bit to temp before overwriting
BitPut(Buff, front, BitGet(Buff, back)); // copy back bit to front bit
BitPut(Buff, back, temp); // copy saved value of front in temp to back of bit arra)
front++;
back--;
}
return Buff;
}
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
int _tmain(int argc, _TCHAR* argv[]) {
int i, j, k, LoopKnt = 1000001;
time_t start;
uchar Buff[BUFF_BYTES];
memset(Buff, 0, sizeof(Buff));
// make an ASCII art picture
for(i=0, k=0; i<(sizeof(Buff)*8)/DW; i++) {
for(j=0; j<DW/2; j++) {
BitSet(Buff, (i*DW)+j+k);
}
k++;
}
// print ASCII art picture
for(i=0; i<sizeof(Buff); i++) {
if(!(i % 10)) printf("\n"); // print bits in blocks of 80
PrintIntBits(Buff[i], 8);
}
i=LoopKnt;
start = clock();
while(i--) {
ReverseBitsInArray((uchar *)Buff, BUFF_BYTES * 8);
}
// print ASCII art pic flipped upside-down and rotated left
printf("\nMilliseconds elapsed = %d", clock() - start);
for(i=0; i<sizeof(Buff); i++) {
if(!(i % 10)) printf("\n"); // print bits in blocks of 80
PrintIntBits(Buff[i], 8);
}
printf("\n\nBenchmark time for %d loops\n", LoopKnt);
getchar();
return 0;
}
// -----------------------------------------------------------------------------
// Scaffolding...
static void PrintIntBits(long x, int bits) {
unsigned long long z=1;
int i=0;
z = z << (bits-1);
for (; z > 0; z >>= 1) {
printf("%s", ((x & z) == z) ? "#" : ".");
}
}
// These routines do bit manipulations on a bit array of unsigned chars
// ---------------------------------------------------------------------------
void BitSet(uchar *buff, unsigned long BitNumber) {
buff[BitNumber >> 3] |= mask_set[BitNumber & 7];
}
// ----------------------------------------------------------------------------
void BitClr(uchar *buff, unsigned long BitNumber) {
buff[BitNumber >> 3] &= mask_clr[BitNumber & 7];
}
// ----------------------------------------------------------------------------
void BitTog(uchar *buff, unsigned long BitNumber) {
buff[BitNumber >> 3] ^= mask_set[BitNumber & 7];
}
// ----------------------------------------------------------------------------
uchar BitGet(uchar *buff, unsigned long BitNumber) {
return (uchar) ((buff[BitNumber >> 3] >> (BitNumber & 7)) & 1);
}
// ----------------------------------------------------------------------------
void BitPut(uchar *buff, unsigned long BitNumber, uchar value) {
if(value) { // if the bit at buff[BitNumber] is true.
BitSet(buff, BitNumber);
} else {
BitClr(buff, BitNumber);
}
}
Di seguito è riportato l'elenco di codice per un'ottimizzazione utilizzando un nuovo buffer, invece di scambiare byte in posizione. Dato che solo 2030: 4080 BitSet() s sono necessari a causa del test if(), e circa la metà di GetBit() e PutBits() vengono eliminati eliminando TEMP, sospetto che il tempo di accesso alla memoria sia un costo fisso elevato per questo tipo di operazioni, fornendo un limite difficile all'ottimizzazione.
Usando un approccio look-up, e CONDIZIONATAMENTE scambiando byte, anziché bit, riduce di un fattore 8 il numero di accessi alla memoria, e di test per un byte 0 ottiene ammortizzati su 8 bit, anziché 1.
Utilizzando questi due approcci, testare per vedere se l'intero char 8-bit è 0 prima di fare ANYTHING, inclusa la ricerca della tabella, e la scrittura, è probabile che sia l'approccio più veloce possibile, ma richiederebbe un extra di 512 byte per il nuovo array di bit di destinazione e 256 byte per la tabella di ricerca. Il rendimento della performance potrebbe essere piuttosto drammatico.
// -----------------------------------------------------------------------------
// Reverse the bit ordering in new array
uchar *ReverseBitsInNewArray(uchar *Dst, const uchar *Src, const int BitKnt) {
int front=0, back = BitKnt-1;
memset(Dst, 0, BitKnt/BitsInByte);
while(front < back) {
if(BitGet(Src, back--)) { // memset() has already set all bits in Dst to 0,
BitSet(Dst, front); // so only reset if Src bit is 1
}
front++;
}
return Dst;
Ho scoperto che i siti di visualizzazione LCD hanno in genere una buona routine per scrivere i dati sui loro moduli (e in entrambe le direzioni). Inoltre, poiché questo è un problema comune, le schede hobbista (e professionali) per il tuo processore probabilmente hanno anche degli algoritmi per farlo. – KevinDTimm
Una cosa, è possibile riordinare i bit all'interno di un byte utilizzando una tabella di ricerca, ad es. '00101101 -> 10110100'. Il resto del problema verrebbe quindi ridotto per invertire rapidamente il buffer a livello di byte. – stakx
Dovresti davvero farlo al volo quando invii i dati al display LCD, non come un pre-pass separato. Vedi [la mia risposta] (http://stackoverflow.com/a/16535315/414813) sotto ... – CAFxX