2010-04-14 5 views
10

que tengo una aplicación de C++ que incluye una serie de estructuras con campos de bits de control manual, algo así comoCómo lenta son campos de bits en C++

#define FLAG1 0x0001 
#define FLAG2 0x0002  
#define FLAG3 0x0004  

class MyClass 
{ 
' 
' 
    unsigned Flags; 

    int IsFlag1Set() { return Flags & FLAG1; } 
    void SetFlag1Set() { Flags |= FLAG1; } 
    void ResetFlag1() { Flags &= 0xffffffff^FLAG1; } 
' 
' 
}; 

Por razones obvias me gustaría cambiar esto para usar los campos de bits , algo así como

class MyClass 
{ 
' 
' 
    struct Flags 
    { 
    unsigned Flag1:1; 
    unsigned Flag2:1; 
    unsigned Flag3:1; 
    }; 
' 
' 
}; 

La única preocupación que tengo con hacer este cambio es que me he encontrado con una serie de referencias en este sitio que indican cómo los campos de bits son lentos en C++. Mi suposición es que todavía son más rápidos que el código manual que se muestra arriba, pero ¿hay algún material de referencia que cubra las implicaciones de velocidad de usar campos de bits en varias plataformas, específicamente ventanas de 32 bits y 64 bits? La aplicación trata con grandes cantidades de datos en la memoria y debe ser rápida y eficiente desde el punto de vista de la memoria, lo que bien podría ser el motivo por el cual se escribió de esta manera en primer lugar.

+4

Tenga en cuenta que los campos de bit son menos portátiles. Si planea que su código se ejecute en plataformas tanto grandes como pequeñas, debe evitarlas. – Bill

+1

Estoy de acuerdo con Bill: los campos de bits realmente son una herramienta de último recurso. No creo haberlos usado durante veinte años o más. –

+0

@Bill, había considerado el problema de Endian, pero dado que los datos incluyen muchos otros enteros, el endian-ness será un problema con la migración entre plataformas en cualquier caso, lo más probable es que se trate durante la serialización. –

Respuesta

4

Los dos ejemplos deben ser muy similares en velocidad porque el compilador tendrá que terminar emitiendo prácticamente las mismas instrucciones para el enmascaramiento de bits en ambos casos. Para saber cuál es realmente el mejor, ejecuta algunos experimentos simples. Pero no se sorprenda si los resultados no son concluyentes; eso es lo que estoy prediciendo ...

Sería mejor decir que los campos de bit son del tipo bool.

+0

algunas arquitecturas tienen instrucciones específicas para acceder a los bits, esp. sistemas embebidos, por lo que el uso de bitfields puede ser más rápido que hacerlo y/o/xor explícitamente si el compilador no es lo suficientemente inteligente. Incluso x86 tiene algunas instrucciones similares como BT, BTC, BTS ... –

4

A menos que esto esté en un bucle muy muy apretado, no habrá nada que elegir entre los dos en el rendimiento, si el rendimiento realmente importa usar bools (es decir, probablemente valores de 32 bits).

El uso de una estructura con solo tres campos de un solo bit como ese todavía rellenará a al menos 32-bits. Si está absolutamente concentrado en guardar cada bit posible, eche un vistazo a la documentación de su compilador sobre alineación y relleno en las estructuras.

EDIT: Una razón para favorecer bit-fields es que hacen un código más limpio, y la importancia de la mantenibilidad no debe subestimarse. ¡En comparación con el tiempo del programador, el tiempo de la computadora es barato!

+0

El ejemplo con 3 bits fue posiblemente engañoso, en realidad tengo 128 bits de datos en 4 enteros sin signo, en una combinación de indicadores de un solo bit y cortos (3 - 7 bit) enumeraciones. Desafortunadamente, el espacio es un problema tan importante como la velocidad, y necesito maximizar ambos a pesar de que están en oposición. Ya estoy organizando mis estructuras para minimizar el relleno y el uso de #pragma pack (1) en algunos lugares como último recurso. –

+0

¡En cuyo caso parece que estás haciendo todo lo que puedes! Sin embargo; si tiene tantos bits que podría hacer algunas cosas astutas si rara vez difieren de los valores predeterminados: por ejemplo, si en promedio << 1/8th de los bits son diferentes de los valores predeterminados, entonces podría utilizar una longitud variable una matriz de bytes para almacenar los índices de los bits que son diferentes. Obviamente, sin embargo, hay implicaciones de rendimiento y complicaciones serias con respecto a la asignación de memoria. – James

1

Consejos generales para este tipo de pregunta: configure un programa simple que compare su situación de la manera más exacta posible (operaciones, hardware, etc.) y mida usted mismo la diferencia en el rendimiento.

Para esta pregunta en bitfields vs enmascaramiento, dudo que vea diferencias de rendimiento significativas: el código del campo de bits puede necesitar un cambio o dos más que el enmascaramiento, según el compilador. Si eso es notable en su aplicación o no, es algo que necesita responder. Por ejemplo, hay una gran diferencia en las consideraciones para el código incrustado programable de máscara frente a las aplicaciones de escritorio.