¿Alguna vez tiene sentido para un compilador para pasar una estructura como esta en un registro de la CPU a una función?

StackOverflow https://stackoverflow.com/questions/4213107

Pregunta

Me gustaría saber si algún tipo de estructura contiene más de una primitiva pero su tamaño total es menor o igual al tamaño de un único registro de la CPU como un registro de 4 bytes, lo hace siempre tiene sentido para un compilador para ponerlo en uno de los registros de 4 bytes cuando se pasa por valor o referencia a una función en lugar de hacer una copia del mismo en la pila destinatario de la llamada o pasar un puntero a la misma y, en general, al pasar a algo más que un sencillo al primitiva una función como una matriz o una estructura podría pasar en un registro de la CPU siempre ser útil?

muestra de tal estructura:

struct sample{
 public:
  char char1;
  char char2;
};

muestra de paso de la estructura a una función:

void someFunc(const sample input){
 //whatever
}
void someFunc(sample input){
 //whatever
}
void someFunc(sample & input){
 //whatever
}
void someFunc(const sample & input){
 //whatever
}
¿Fue útil?

Solución

Sí. Muchos compiladores tienen un atributo clave o tipo especial que se puede utilizar para especificar que una estructura se debe pasar en los registros en lugar de en la pila. Es más común en los procesadores que tienen muchos registros y tuberías profundas, como el PowerPC, y puede ser una enorme mejora del rendimiento en arquitecturas donde escribir un valor en la memoria y luego leerlo de nuevo de inmediato provoca un puesto de tubería.

Por lo general, sería sólo lo utilizan para una estructura que es del mismo tamaño que un registro nativo. En particular, es útil en los procesadores que han SIMD amplia registros, que pueden pasar a 16 bytes de una vez o más. Eso permitirá pasar (por ejemplo) un vector unidimensional 4 (cuatro flotadores) en un registro. de AMD System V es un ejemplo de un sistema x86 ABI que permite esto.

Un ejemplo diferente es atributo de tipo d64_abi de GCC, que le dice a un PowerPC para pasar una estructura en un registro cuando sea posible, en lugar de en la pila. (Esto es parte de la Darwin ABI ).

typedef struct {
    int          a;
    float        f;
    char         c;
} __attribute__ ((d64_abi)) Thingy;

Thingy foo( Thingy t );

En el caso anterior, una llamada a Foo pasaría esa cosa en un registro flotador y dos registros int, en lugar de escribir a la pila y la lectura de las cosas bien de nuevo. El valor de retorno regresa en un registro de la misma manera.

nunca he visto un compilador que lo hace automáticamente, sin necesidad de decírselo, pero es posible que exista uno.

Otros consejos

Esto se define en el interfaz de aplicación binaria (ABI) de su entorno ejecución. La norma no dice nada acerca de los registros del procesador cuando una función es llamada, por lo que es legal para crear un ambiente donde las pequeñas estructuras se empaquetan en un único registro del procesador.

En la pieza de referencia, que son muy probable que se traslade como punteros de todos modos, ya que al interior de la función llamada se toma la dirección de una referencia, debe resolverse en la dirección del objeto referenciado.

En ciertas arquitecturas (como i386, sé que es antiguo, pero eso es lo que crecí;) sin duda tiene sentido para pasarlo en un registro, ya empujando y haciendo estallar de la pila tomar mucho más (es decir, entre 3 -6 veces más) ciclos de la CPU como pasar por el registro. Por lo que un compilador hacer un buen trabajo optimizando para ello.

Me imagino que hay otras arquitecturas donde no importa. O si los registros están en uso para otras optimizaciones que producen una mayor mejoría, no tiene sentido usarlos para esto.

Lo que está usando la arquitectura / focalización, o está pidiendo en general?

Creo que hay compiladores que pasará POD en los registros, incluso si son structs.

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