2010-05-19 23 views
10

Como aclaración: Yo sé cómo el mal son globales y cuando no usarlos :)C++ de variables globales

  • ¿Hay alguna penalización en el rendimiento cuando se accede a/Establecer una variable global frente a una local en una compilado programa de C++?
+5

Una mejor pregunta sería "¿Por qué es importante?" Cuando alguien comienza a micro-optimizar detalles como este, me dice que tienen un problema de rendimiento y que están buscando formas de solucionarlo. Si ese es el caso, * perfil * y encuentre los cuellos de botella. No te preocupes por este tipo de cosas. No vale la pena tu tiempo. – greyfade

+0

De todos modos, creo que finalmente he encontrado la manera de impulsar mi representante sin demasiada molestia: es suficiente hacer una pregunta con "rendimiento" en el medio y de repente obtienes tantos votos que no sabes qué hacer ¡con ellos! –

+0

"Sé cómo son los malvados globales y cuándo no usarlos": nunca hay una buena razón para usar una variable global, solo la pereza. Los únicos globales que debes tener son constantes. –

Respuesta

5

Estrictamente hablando, no.

Algunas cosas a considerar: Las variables globales aumentan el tamaño estático de su programa en la memoria. Si el acceso a la variable necesita sincronizarse, eso podría generar algunos gastos generales de rendimiento.

20

Eso dependería completamente de la arquitectura de su máquina. Se accede a las variables globales a través de una sola dirección conocida, mientras que las variables locales se acceden generalmente mediante la indexación de un registro de direcciones. Las posibilidades de que la diferencia entre las dos sea significativa son extremadamente remotas, pero si cree que será importante, debe escribir una prueba para su arquitectura objetivo y medir la diferencia.

+0

¿Por qué tanto depende de la arquitectura de mi máquina ?(Eso hace las cosas difíciles de optimizar –

+1

Si está buscando optimizar su programa debería estar perfilando y encontrando los cuellos de botella sin adivinar dónde podrían estar los cuellos de botella. Acceso corto a su global, a menudo de una manera que destruye por completo el caché, casi seguro que no se verá nada relacionado con esto como un cuello de botella. –

+4

@Dr. Acula Las computadoras son máquinas del mundo real, conceptos no idealizados. Si necesita que se ejecute su código tan rápido como sea posible, debe abordar las diversas peculiaridades de la máquina del mundo real. Por supuesto, el 99,99% de las veces no necesita que su código se ejecute lo más rápido posible, solo lo suficientemente rápido, en cuyo caso no debería incluso piense en la optimización, pero deje las cosas al compilador. –

7

Depende, pero generalmente sí, aunque es un problema micro. Las variables globales deberían ser referenciables desde muchos contextos, lo que significa que no es posible incluirlas en un registro. Mientras que en el caso de las variables locales, eso es posible y preferible. De hecho, cuanto más estrecho es el alcance, más compilador tiene la oportunidad de optimizar el acceso/modificación de esa variable.

+1

En realidad, puede poner una variable global en un registro en gcc: registrar unsigned long * ds asm ("ebx"); pero probablemente sea más lento, ya que está muriendo de hambre a toda la base de código de un registro. – geocar

5

Existen varias optimizaciones del compilador que son posibles con variables locales pero no con variables globales, por lo que en algunos casos puede ver una diferencia en el rendimiento. Sin embargo, dudo que se esté accediendo a su variable global en un ciclo de rendimiento crítico (¡muy mal diseño si lo es!) Por lo que probablemente no sea un problema.

2

La respuesta está ligada a la estructura general del programa.

Por ejemplo, acabo de desmontar esta, y en ambos casos la variable de bucle fue trasladado en un registro, después de lo cual no hubo una diferencia:

int n = 9; 
int main() 
{ 
    for (n = 0; n < 10; ++n) 
     printf("%d", n); 

    for (int r = 0; r < 10; ++r) 
     printf("%d", r); 

    return 0; 
} 

sólo para estar seguro, hice cosas similares con las clases y nuevamente no vimos ninguna diferencia. Pero si el global está en una unidad de compilación diferente que podría cambiar.

6

Las variables locales son probablemente "más rápidas" en muchos casos, pero no creo que la ganancia de rendimiento sea notable o supere el costo de mantenimiento adicional de tener muchas variables globales. Todo lo que menciono a continuación tiene un costo insignificante o puede ser eclipsado fácilmente por casi cualquier otra ineficiencia en su programa. Consideraría que estos son un ejemplo perfecto de una micro-optimización.

Las variables locales están en la pila, que es más probable que estén en la caché. Este punto es discutible si su variable global se utiliza con frecuencia, ya que, por lo tanto, también estará en la memoria caché.

Las variables locales tienen un alcance para la función; por lo tanto, el compilador puede presumir que no se cambiarán por ninguna otra llamada a función. Con un global, el compilador puede verse obligado a volver a cargar el valor global.

En algunas máquinas de 64 bits, obtener la dirección de una variable global es un proceso de dos pasos; también debe agregar el desplazamiento de 32 bits de la dirección base global a la de 64 bits. Siempre se puede acceder directamente a las variables locales desde el puntero de la pila.

1

No hay ninguna penalización de rendimiento, de cualquier forma, que deba preocuparle. Además de lo que han dicho todos los demás, también debes tener en cuenta que la página está sobrecargada. Las variables de instancia locales se extraen de la estructura de objetos que probablemente (?) Ya se haya paginado en la memoria caché. Las variables globales, por otro lado, pueden causar un patrón diferente de paginación de memoria virtual.

De nuevo, el rendimiento realmente no merece ninguna consideración por su parte.

1

Además de otras respuestas, simplemente señalaría que acceder a una variable global en un entorno multiproceso es probable que sea más costoso porque necesita asegurarse de que está bloqueado correctamente y los hilos pueden esperar en la cola para acceder a él. Con las variables locales no es un problema.

1

Más que nada cómo se usan los datos almacenados en las variables es importante para el rendimiento y luego cómo se declaran. No estoy seguro acerca de la terminología correcta aquí, pero uno puede definir dos tipos de acceso a datos. Acceso compartido (donde accede a los mismos datos de diferentes partes del código) y datos privados, donde cada parte tiene sus propios datos. Por defecto, las variables globales implican acceso compartido e implican acceso privado local. Pero ambos tipos de acceso se pueden lograr con ambos tipos de variables (es decir, punteros locales que apuntan al mismo fragmento de memoria, o matriz global donde cada parte del código accede a una parte diferente de la matriz).

El acceso compartido tiene mejor almacenamiento en caché, menor huella de memoria, pero es más difícil de optimizar, especialmente en entornos de múltiples hilos. También es malo para escalar especialmente con la arquitectura NUMA.

El acceso privado es más fácil de optimizar y mejor para escalar. Los problemas con el acceso privado generalmente existen en situaciones en las que tiene copias múltiples de la misma información. Los problemas generalmente asociados con estos escenarios son una mayor huella de memoria, sincronización entre copias, peor almacenamiento en caché, etc.