2008-08-30 9 views
8

Mayor K & R (2ª ed.) Y otros textos de lenguaje C He leído que discutir la implementación de un asignador de memoria dinámica en el estilo de malloc() y free() por lo general también mencionar , de paso, algo sobre las restricciones de alineación del tipo de datos. Aparentemente, ciertas arquitecturas de hardware (CPU, registros y acceso a la memoria) restringen la forma en que puede almacenar y tratar ciertos tipos de valores. Por ejemplo, puede haber un requisito de que un entero de 4 bytes (long) debe almacenarse comenzando en direcciones que son múltiplos de cuatro.restricciones de alineación para malloc()/free()

¿Qué restricciones, si las hay, las principales plataformas (Intel & AMD, SPARC, Alpha) imponen la asignación de memoria y el acceso a la memoria, o puedo ignorar las asignaciones de memoria en límites de direcciones específicos?

Respuesta

4

La alineación sigue siendo bastante importante en la actualidad. Algunos procesadores (la familia de los 68k salta a la mente) lanzaban una excepción si intentabas acceder a un valor de palabra en un límite impar. Hoy, la mayoría de los procesadores ejecutarán dos ciclos de memoria para buscar una palabra desalineada, pero esto definitivamente será más lento que una búsqueda alineada. Algunos otros procesadores ni siquiera lanzarán una excepción, ¡pero obtendrán un valor incorrecto de la memoria!

Si no es por otra razón que el rendimiento, es aconsejable tratar de seguir las preferencias de alineación de su procesador. Por lo general, su compilador se encargará de todos los detalles, pero si está haciendo algo donde usted mismo diseñe la estructura de la memoria, entonces vale la pena considerarlo.

1

Aún debe tener en cuenta los problemas de alineación al diseñar una clase o estructura en C (++). En estos casos el compilador va a hacer lo correcto para usted, pero el tamaño total de la estructura/clase puede ser más wastefull de lo necesario

Por ejemplo:

struct 
{ 
    char A; 
    int B; 
    char C; 
    int D; 
}; 

tendría un tamaño de 4 * 4 = 16 bytes (Suponga Windows en x86), mientras que

struct 
{ 
    char A; 
    char C; 
    int B; 
    int D; 
}; 

tendría un tamaño de 4 * 3 = 12 bytes.

Esto se debe a que el compilador impone una alineación de 4 bytes para los enteros, pero solo 1 byte para los caracteres.

En general, empaqueta las variables de miembros del mismo tamaño (tipo) juntas para minimizar el espacio desperdiciado.

1

Como Greg mencionó, sigue siendo importante hoy en día (tal vez más en algunos aspectos) y los compiladores generalmente se encargan de la alineación según el objetivo de la arquitectura. En entornos administrados, el compilador JIT puede optimizar la alineación en función de la arquitectura de tiempo de ejecución.

Puede ver las directivas pragma (en C/C++) que cambian la alineación. Esto solo debe usarse cuando se requiere una alineación muy específica.

// For example, this changes the pack to 2 byte alignment. 
#pragma pack(2) 
6

Sparc, MIPS, Alpha, y la mayoría de otras arquitecturas RISC "clásica" sólo se permiten alinear los accesos a memoria, incluso hoy en día. Un acceso desalineado causará una excepción, pero algunos sistemas operativos manejarán la excepción copiando desde la dirección deseada en el software usando cargas y tiendas más pequeñas. El código de la aplicación no sabrá que hubo un problema, excepto que el rendimiento será muy malo.

MIPS tiene instrucciones especiales (lwl e lwr) que pueden usarse para acceder a cantidades de 32 bits desde direcciones no alineadas. Siempre que el compilador pueda decir que la dirección probablemente no está alineada, usará estas dos secuencias de instrucciones en lugar de una instrucción lw normal.

x86 puede manejar accesos de memoria no alineados en hardware sin excepción, pero todavía hay un rendimiento de hasta 3 veces en comparación con los accesos alineados.

Ulrich Drepper escribió un documento completo sobre este y otros temas relacionados con la memoria, What Every Programmer Should Know About Memory. Es un relato muy largo, pero lleno de bondad masticable.

1

Tenga en cuenta que incluso en IA-32 y AMD64, algunas de las instrucciones/intrínsecas de SSE requieren datos alineados. Estas instrucciones emitirán una excepción si los datos no están alineados, por lo que al menos no tendrá que depurar errores de "datos incorrectos". También hay instrucciones desalineadas equivalentes, pero, como dice Denton, son más lentas.

Si está utilizando VC++, además de las directivas #pragma pack, también tiene las directivas __declspec (alinear) para una alineación precisa. La documentación de VC++ también menciona una función __aligned_malloc para requisitos de alineación específicos.

Como regla general, a menos que mueva datos a través de compiladores/idiomas o esté usando las instrucciones SSE, probablemente pueda ignorar los problemas de alineación.