Pregunta

Estoy haciendo una biblioteca de vector / matriz. (GCC, ARM NEON, iPhone)

typedef struct{ float v[4]; } Vector;
typedef struct{ Vector v[4]; } Matrix;

Me pasa los datos struct como puntero para evitar degradar el rendimiento de la copia de datos cuando se llama a la función. Por lo tanto, la función diseñado como esto al principio:

void makeTranslation(const Vector* factor, Matrix* restrict result);

Pero, si la función es en línea, ¿hay alguna razón para pasar valores como puntero para el rendimiento? ¿Esas variables que se copian también? ¿Qué hay de registro y cachés? Traté de función como esta rediseñar:

inline Matrix makeTranslation(const Vector factor) __attribute__ ((always_inline));

¿Cómo cree en llamar a los costos de cada uno de los casos?

  • I añadió 'const' a segunda firma para reflejar las sugerencias.
¿Fue útil?

Solución

Cuando la función está en línea normalmente Prohibida la reproducción de las variables está involucrado directamente con la llamada. Variables serán todavía pueden mover y poner en la pila a veces como una parte normal de la ejecución, pero no como un resultado directo de la llamada a la función. (Cuando se le acaba de registros, algunos valores pueden llegar a poner en la pila, etc ... pero sólo si es necesario.) Así que la sobrecarga de la "llamada" básicamente desaparece cuando se inline una función (No más la configuración / derribando el marco de pila, salto incondicional no más, no más de empuje / poping parámetros.)

Si se puede confiar en su atributo always_inline a siempre En línea la función, entonces debería tampoco pasar el puntero por vectorial (si no es modificada). La razón de esto es que pasar de largo puntero requiere la dirección del vector de ser tomada, lo que significa que el compilador debe asegurarse de que tiene una dirección y por lo tanto no puede existir sólo en registros de la CPU. Esto puede ralentizar las cosas si no es necesario, y cuando se toma la dirección de algo que el compilador siempre se asegurará de que tiene una dirección debido a que el compilador no puede estar seguro de que no es necesaria la dirección.

Debido al paso-a-puntero, este código SIEMPRE tendrá una instrucción para obtener la dirección del objeto, y al menos un desreferenciar para conseguir a su valor de un miembro. Si pasa por valor, entonces esto todavía puede suceder, pero el compilador puede ser capaz de optimizar todo eso de distancia.

No se olvide que el uso excesivo de inlining puede aumentar significativamente el tamaño del compilador de código binario. En ciertos casos que tienen segmentos de código de gran tamaño (como resultado de las funciones en línea) puede causar más errores de caché de instrucciones con resultará en un rendimiento más lento porque la CPU está constantemente tener que salir a la memoria principal a buscar partes de su programa, porque algunos de ellos es demasiado grande para caber en la pequeña caché L1. Esto puede ser especialmente importante en procesadores embebidos (como el iPhone), ya que estos procesadores tienen típicamente pequeñas memorias caché.

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