tipos repentina por perdida para memoria medicamentos jovenes inmediata enfermedades enfermedad caracteriza ancianos c assembly x86 stack processing-efficiency

repentina - se caracteriza por la perdida de memoria inmediata



Costo de empuje frente a mov(pila frente a memoria cercana) y sobrecarga de llamadas a funciĆ³n (2)

Hoy en día, su compilador de C puede ser más astuto que usted. Puede alinear funciones simples y, si lo hace, no habrá llamada o retorno de función y, tal vez, no habrá manipulaciones de pila adicionales relacionadas con pasar y acceder a los parámetros de función formales (o una operación equivalente cuando la función está en línea, pero el los registros disponibles están agotados) si todo puede hacerse en registros o, mejor aún, si el resultado es un valor constante y el compilador puede ver eso y aprovecharlo.

Las llamadas a funciones pueden ser relativamente baratas (pero no necesariamente de costo cero) en las CPU modernas, si se repiten y si hay una caché de instrucciones separada y varios mecanismos de predicción, lo que ayuda a la ejecución eficiente del código.

Aparte de eso, esperaría que las implicaciones de rendimiento de la opción "var local versus var global" dependan de los patrones de uso de la memoria. Si hay un caché de memoria en la CPU, es probable que la pila esté en ese caché, a menos que asigne y desasigne arreglos o estructuras grandes en él o tenga llamadas a funciones profundas o recursión profunda, lo que provocará errores de caché. Si se accede a la variable global de interés a menudo o si se accede a sus vecinos a menudo, también esperaría que la variable esté en el caché la mayor parte del tiempo. Nuevamente, si accede a grandes espacios de memoria que no caben en la memoria caché, tendrá fallas en la memoria caché y posiblemente un rendimiento reducido (posiblemente porque puede haber o no una mejor manera de hacer lo que quiero hacer).

Si el hardware es bastante tonto (no hay cachés pequeños, no hay predicción, no hay reordenamiento de instrucciones, no hay ejecución especulativa, nada), claramente quiere reducir la presión de la memoria y el número de llamadas a funciones porque cada uno contará.

Otro factor más es la longitud de la instrucción y la decodificación. Las instrucciones para acceder a una ubicación en la pila (relativa al puntero de la pila) pueden ser más cortas que las instrucciones para acceder a una ubicación de memoria arbitraria en una dirección determinada. Las instrucciones más cortas se pueden decodificar y ejecutar más rápido.

Diría que no hay una respuesta definitiva para todos los casos porque el rendimiento depende de:

  • tu hardware
  • tu compilador
  • su programa y sus patrones de acceso a la memoria

Pregunta:

¿El acceso a la pila es la misma velocidad que el acceso a la memoria?

Por ejemplo, podría elegir hacer algún trabajo dentro de la pila, o podría trabajar directamente con una ubicación etiquetada en la memoria.

Entonces, específicamente: ¿el push ax la misma velocidad que mov [bx], ax ? ¿Igualmente es pop ax la misma velocidad que mov ax, [bx] ? (supongamos que bx tiene una ubicación near memoria).

Motivación para la pregunta:

Es común en C desalentar funciones triviales que toman parámetros.

Siempre pensé que eso se debe a que los parámetros no solo se insertan en la pila y luego se eliminan de la pila una vez que la función retorna, sino también porque la llamada a la función debe preservar el contexto de la CPU, lo que significa un mayor uso de la pila.

Pero suponiendo que uno conoce la respuesta a la pregunta principal, debería ser posible cuantificar la sobrecarga que usa la función para configurarse (presionar / soltar / preservar el contexto, etc.) en términos de un número equivalente de accesos directos a la memoria. De ahí la pregunta principal.

( Editar : Aclaración: near uso anterior es diferente al más far en el modelo de memoria segmentada de la arquitectura x86 de 16 bits).

Para el reloj-ciclo-curioso ...

Para aquellos a quienes les gustaría ver ciclos de reloj específicos, las tablas de instrucciones / latencia para una variedad de modernas CPUs x86 y x86-64 están disponibles here (gracias a hirschhornsalz por señalarlas).

Luego obtienes, en un chip Pentium 4:

  • push ax y mov [bx], ax (caja roja) son virtualmente idénticos en su eficiencia con latencias y rendimientos idénticos.
  • pop ax y mov ax, [bx] (caja azul) son igualmente eficientes, con rendimientos idénticos a pesar de mov ax, [bx] tienen el doble de latencia de pop ax

En cuanto a la pregunta de seguimiento en los comentarios (tercer comentario):

  • direccionamiento indirecto (es decir, mov [bx], ax ) no es materialmente diferente que el direccionamiento directo (es decir, mov [loc], ax ), donde loc es una variable que tiene un valor inmediato, por ejemplo, loc equ 0xfffd .

Conclusión: Combine esto con here , y hay un caso bastante sólido para la eficiencia de usar la pila y dejar que el compilador decida cuándo se debe incluir una función.

(Nota al margen: de hecho, incluso ya en el 8086 de 1978, el uso de la pila no era menos eficiente que los correspondientes mov a la memoria, como se puede ver en estas viejas tablas de tiempo de instrucción 8086 ).

Comprender la latencia y el rendimiento

Se puede necesitar un poco más para comprender las tablas de tiempos para las CPU modernas. Esto debería ayudar: