Pregunta

Actualmente estoy intentando crear un código que se supone que funciona en una amplia gama de máquinas, desde bolsillos y sensores portátiles hasta grandes servidores en centros de datos.

Una de las (muchas) diferencias entre estas arquitecturas es el requisito de acceso alineado a la memoria.

No se requiere acceso a la memoria alineada en la CPU x86 "estándar", pero muchas otras CPU lo necesitan y producen una excepción si no se respeta la regla.

Hasta ahora, me he ocupado de ello obligando al compilador a tener cuidado con los accesos de datos específicos que se sabe que son riesgosos, utilizando el atributo empaquetado (o pragma). Y funciona bien.

El problema es que el compilador es tan cauteloso que se pierde mucho rendimiento en el proceso.

Dado que el rendimiento es importante, sería mejor reescribir una parte del código para trabajar específicamente en cpus estrictamente alineados. Dicho código, por otro lado, sería más lento en cpus que admiten acceso a memoria no alineado (como x86), por lo que queremos usarlo solo en cpus que requieren acceso a memoria estrictamente alineado.

Y ahora la pregunta: ¿Cómo detectar, en tiempo de compilación, que la arquitectura de destino requiere acceso a memoria estrictamente alineado? (o al revés)

¿Fue útil?

Solución

No conozco ninguna implementación de C que proporcione ninguna macro de preprocesador para ayudarlo a resolver esto. Dado que su código supuestamente se ejecuta en una amplia gama de máquinas, supongo que tiene acceso a una amplia variedad de máquinas para realizar pruebas, por lo que puede averiguar la respuesta con un programa de prueba. Luego, puede escribir su propia macro, algo como a continuación:

#if defined(__sparc__)
/* Unaligned access will crash your app on a SPARC */
#define ALIGN_ACCESS 1
#elif defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC)
/* Unaligned access is too slow on a PowerPC (maybe?) */
#define ALIGN_ACCESS 1
#elif defined(__i386__) || defined(__x86_64__) || \
      defined(_M_IX86) || defined(_M_X64)
/* x86 / x64 are fairly forgiving */
#define ALIGN_ACCESS 0
#else
#warning "Unsupported architecture"
#define ALIGN_ACCESS 1
#endif

Tenga en cuenta que la velocidad de un acceso no alineado dependerá de los límites que cruce. Por ejemplo, si el acceso cruza el límite de una página de 4k, será mucho más lento y puede haber otros límites que lo hagan aún más lento. Incluso en x86, algunos accesos no alineados no son manejados por el procesador y son manejados por el kernel del SO. Eso es increíblemente lento

Tampoco hay garantía de que una implementación futura (o actual) no cambie repentinamente las características de rendimiento de los accesos no alineados. Esto ha ocurrido en el pasado y puede suceder en el futuro; el PowerPC 601 era muy tolerante con el acceso no alineado, pero el PowerPC 603e no lo era.

Para complicar aún más las cosas, está el hecho de que el código que escribiría para hacer un acceso no alineado diferiría en la implementación entre plataformas. Por ejemplo, en PowerPC se simplifica por el hecho de que x << 32 y x >> 32 siempre son 0 si x es de 32 bits, pero en x86 no tienes esa suerte.

Otros consejos

De todos modos, escribir su código para una alineación estricta de la memoria es una buena idea.Incluso en los sistemas x86 que permiten el acceso no alineado, sus lecturas / escrituras no alineadas causarán dos accesos a la memoria y se perderá parte del rendimiento.No es difícil escribir código eficiente que funcione en todas las arquitecturas de CPU.La regla simple para recordar es que el puntero debe estar alineado con el tamaño del objeto que está leyendo o escribiendo.p.ej.si escribe un DWORD, entonces (dest_pointer & 3== 0).El uso de una muleta como los tipos "UNALIGNED_PTR" hará que el compilador genere código ineficiente.Si tiene una gran cantidad de código heredado que debe funcionar inmediatamente, entonces tiene sentido usar el compilador para "arreglar" la situación, pero si es su código, entonces escríbalo desde el principio para que funcione en todos los sistemas.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top