Pregunta

Mi función será llamada miles de veces. Si quiero hacerlo más rápido, va a cambiar las variables de la función local sea estática de alguna utilidad? Mi lógica detrás de esto es que, debido a las variables estáticas son persistentes entre las llamadas de función, que se asignan sólo la primera vez, y por lo tanto, cada llamada posterior no se puede asignar memoria para ellos y serán más rápidas, debido a que el paso de asignación de memoria no se hace.

Además, si lo anterior es cierto, entonces sería el uso de variables globales en lugar de ser más rápido parámetros para pasar información a la función cada vez que se llama? Creo que el espacio de parámetros también se asigna en cada llamada a la función, para permitir la recursividad (por eso usos recursividad más memoria), pero ya que mi función no es recursivo, y si mi razonamiento es correcto, entonces despegando parámetros en la teoría de maquillaje que sea más rápido.

Sé que estas cosas que quiero hacer son los hábitos de programación horribles, pero por favor, dime si es inteligente. Voy a intentarlo de todos modos, pero por favor, dame tu opinión.

¿Fue útil?

Solución

La sobrecarga de las variables locales es cero. Cada vez que se llama a una función, ya la creación de la pila para los parámetros, valores de retorno, etc. Adición de medios variables locales que va a añadir un número ligeramente mayor para el puntero de pila (un número que se calcula en tiempo de compilación) .

Además, las variables locales son probablemente más rápido debido a la localidad de caché.

Si sólo está llamando a su función "miles" de veces (no millones o mil millones), entonces usted debe buscar en su algoritmo para las oportunidades de optimización después que haya ejecutado un generador de perfiles.


Re: localidad caché ( leer más aquí ): variables globales se accede con frecuencia tienen probablemente localidad temporal. También se pueden copiar en un registro durante la ejecución de la función, pero estará de regreso en la memoria (caché) después devuelve una función escrita (de otro modo no serían accesibles a cualquier otra cosa; registros no tienen direcciones).

Las variables locales en general, tendrá tanto localidad temporal y espacial (que consiguen que en virtud de que se está creando en la pila). Además, pueden ser "asignan" directamente a los registros y nunca se escriben en la memoria.

Otros consejos

La mejor manera de averiguarlo es realmente ejecutar un generador de perfiles. Esto puede ser tan simple como ejecutar varias pruebas cronometradas usando ambos métodos y luego promediando los resultados y comparar, o se puede considerar una herramienta de perfilado completo soplado que se une a un proceso y gráficos a cabo el uso de memoria en el tiempo y la velocidad de ejecución.

No lleve a cabo al azar código de ajuste micro porque tiene una sensación visceral de que será más rápido. Los compiladores todos tienen ligeramente diferentes implementaciones de las cosas y lo que es cierto en un compilador en un entorno puede ser falso en otra configuración.

Para hacer frente a ese comentario acerca de un menor número de parámetros: el proceso de "inline" funciones esencialmente elimina la sobrecarga relacionada con la llamada a una función. Lo más probable es una pequeña función será automáticamente en bordeada por el compilador, pero puede sugieren una función ser inline también.

En un idioma diferente, C ++, el nuevo estándar que sale soportes de reenvío perfecto, y semántica movimiento perfecto con referencias rvalue que elimina la necesidad de que los temporales en ciertos casos que pueden reducir el costo de la llamada a una función.

Sospecho que estés prematuramente optimizar, sin embargo, no debe ser esto que ver con el rendimiento hasta que haya descubierto sus verdaderos cuellos de botella.

Absolutamente no! La única diferencia "rendimiento" es cuando las variables se inicializan

    int anint = 42;
 vs
    static int anint = 42;

En el primer caso el número entero se establecerá en 42 cada vez que la función se llama en el segundo caso ot será ajustado a 42 cuando se carga el programa.

Sin embargo, la diferencia es tan trivial como para ser apenas perceptible. Es un error común que el almacenamiento tiene que ser asignado para las variables "automáticas" en cada llamada. Esto no es así C utiliza el espacio ya asignados en la pila para estas variables.

Las variables estáticas en realidad puede retrasar por algunos como sus optimizaciones agresivas no son posibles en las variables estáticas. También como los locales están en un área contigua de la pila son más fáciles de caché de manera eficiente.

No hay una respuesta a esto. Que variará con la CPU, el compilador, las opciones del compilador, el número de variables locales que tiene, lo que la CPU ha estado haciendo antes de llamar a la función, y muy posiblemente la fase de la luna.

Considere dos extremos; si tiene sólo una o unas pocas variables locales, que / que puede ser fácilmente almacenado en los registros en lugar de ser asignado posiciones de memoria en absoluto. Si el registro de "presión" es suficientemente baja para que esto puede ocurrir sin ejecutar ninguna instrucción en absoluto.

En el extremo opuesto hay algunas máquinas (por ejemplo, unidades centrales de IBM) que no tienen pilas en absoluto. En este caso, lo que normalmente se le ocurriría como marcos de pila en realidad están asignadas como una lista enlazada en el montón. Como usted probablemente adivinar, esto puede ser muy lento.

Cuando se trata de acceder a las variables, la situación es algo similar - el acceso a un registro máquina está bastante bien garantiza que sea más rápido que cualquier otra cosa en la memoria asignada puede esperanza posible para. Otoh, es posible que el acceso a las variables en la pila a ser bastante lento - que normalmente requiere algo así como un acceso indirecto indexada, que (especialmente con CPUs antiguas) tiende a ser bastante lento. Otoh, el acceso a un mundial (que una estática es, a pesar de su nombre no es globalmente visible) requiere típicamente la formación de una dirección absoluta, que algunos CPUs penalize en algún grado también.

En pocas palabras: incluso el asesoramiento a perfilar su código puede estar fuera de lugar - la diferencia puede ser fácilmente tan pequeña que incluso un generador de perfiles no lo detectará de forma fiable, y el solamente manera de estar seguro es examinar el lenguaje ensamblador que se produce (y pasar unos años aprender el lenguaje ensamblador lo suficiente para saber que decir nada cuando lo mirada en ella). La otra cara de esto es que cuando usted está tratando con una diferencia ni siquiera se puede medir de forma fiable, las posibilidades de que va a tener un efecto significativo sobre la velocidad de código real es tan remota que es probable que no vale la pena.

Parece que la estática vs no estático ha sido completamente cubierto, pero en el tema de las variables globales. A menudo, estos se ralentizará una ejecución de programas en lugar de acelerarlo.

La razón es que las variables de fuerza de ámbito que sea fácil para que el compilador en gran medida a optimizar, si el compilador tiene que buscar por todas partes su solicitud de instancias de un mundial donde podrían utilizarse entonces su optimización no será tan buena.

Esto se agrava cuando se introduce punteros, supongamos que tiene el siguiente código:

int myFunction()
{
    SomeStruct *A, *B;
    FillOutSomeStruct(B);
    memcpy(A, B, sizeof(A);
    return A.result;
}

el compilador sabe que el puntero A y B pueden no superposición y por lo que pueden optimizar la copia. Si A y B son globales entonces podrían posiblemente apuntan a la superposición o la memoria idénticos, esto significa que el compilador debe 'jugar a lo seguro', que es más lento. El problema generalmente se llama 'puntero aliasing' y puede ocurrir en muchas situaciones no sólo copias de memoria.

http://en.wikipedia.org/wiki/Pointer_alias

Sí, el uso de variables estáticas hará una función de un poquito más rápido. Sin embargo, esto causará problemas si alguna vez desea hacer su programa multi-hilo. Dado que las variables estáticas son compartidos entre invocaciones de funciones, invocando la función de forma simultánea en diferentes hilos dará como resultado un comportamiento indefinido. Multi-threading es el tipo de cosa que usted puede hacer en el futuro para realmente acelerar su código.

La mayoría de las cosas que usted ha mencionado se conocen como micro-optimizaciones. En general, preocuparse por este tipo de cosas es un mala idea . Esto hace que su código sea más difícil de leer, y más difícil de mantener. También es altamente probable que introduzca errores. Probablemente obtendrá más por su dinero haciendo optimizaciones en un nivel superior.

Como sugerencias M2TM, la ejecución de un perfilador es también una buena idea. Echa un vistazo a gprof por uno que es bastante fácil de usar .

Siempre se puede medir el tiempo de su aplicación para determinar realmente lo que es más rápido. Esto es lo que entiendo: (todo esto depende de la arquitectura del procesador, por cierto)

funciones

C crean un marco de pila, que es donde se ponen los parámetros pasados, y las variables locales se ponen, así como la parte de atrás del puntero de retorno a la persona que llama cuando llama a la función. No hay ninguna asignación de la gestión de memoria aquí. Por lo general, un simple movimiento del puntero y eso es todo. Acceso a los datos de la pila también es bastante rápido. Las sanciones por lo general entran en juego cuando se trata con los punteros.

En cuanto a las variables globales o estáticas, que son la misma ... desde el punto de vista de que van a ser asignados en la misma región de la memoria. El acceso a estos pueden utilizar un método diferente de acceso que las variables locales, depende del compilador.

La principal diferencia entre los escenarios es la huella de la memoria, no tanto la velocidad.

El uso de variables estáticas en realidad puede hacer que el código significativamente más lenta . Las variables estáticas deben existir en una región 'datos' de la memoria. Con el fin de utilizar esa variable, la función debe ejecutar una instrucción de carga para leer desde la memoria principal, o una instrucción de almacenamiento de escribir en él. Si esa región no está en la caché, se pierde muchos ciclos. Una variable local que vive en la pila lo más seguro que tienen una dirección que está en la caché, e incluso podría estar en un registro de la CPU, no aparezcan en la memoria en absoluto.

Estoy de acuerdo con los otros comentarios acerca de perfiles para averiguar cosas por el estilo, pero en términos generales, las variables estáticas función debe ser más lento. Si los quieres, lo que realmente después de un mundial. estática Insertar función código / datos para comprobar si la cosa ha sido ya que consigue ejecutarse cada vez que su función es llamada inicializado.

perfiles no puede ver la diferencia, desmontaje y saber qué buscar fuerzas.

sospecho que sólo se va a conseguir una variación tanto como unos pocos ciclos de reloj por bucle (en promedio dependiendo del compilador, etc.). A veces, el cambio será espectacular mejora drásticamente o más lento, y que no será necesariamente porque las variables de la casa se ha movido hacia / desde la pila. Digamos que usted ahorra cuatro ciclos de reloj por llamada a la función de 10000 llamadas en un procesador de 2GHz. cálculo muy aproximado: 20 microsegundos guardados. Es de 20 microsegundos mucho o poco en comparación con el tiempo de ejecución actual?

Es probable que obtener más de una mejora en el rendimiento al hacer la totalidad de su carbón y las variables cortas en enteros, entre otras cosas. Micro-optimización es una buena cosa para saber, pero lleva un montón de tiempo experimentando, desmontaje, el momento de la ejecución de su código, la comprensión de que un menor número de instrucciones no significa necesariamente más rápido, por ejemplo.

Tome su programa específico, desmontar tanto la función de que se trate y el código que llama. Con y sin la estática. Si aumenta de sólo uno o dos instrucciones y esta es la única optimización que se va a hacer, es probable que no vale la pena. Puede no ser capaz de ver la diferencia, mientras que perfilado. Cambios en donde las líneas de aciertos de caché podría aparecer en los perfiles antes de cambios en el código de ejemplo.

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