¿Por qué n++ se ejecuta más rápido que n=n+1?


En lenguaje C, ¿por qué n++ se ejecuta más rápido que n=n+1?

(int n=...;  n++;)
(int n=...;  n=n+1;)

Nuestro instructor hizo esa pregunta en la clase de hoy. (esto no es tarea)

Author: Betamoo, 2010-05-21

10 answers

Eso sería cierto si está trabajando en un compilador "stone-age"...

En el caso de "edad de piedra":
++n es más rápido que n++ es más rápido que n=n+1
La máquina generalmente tiene increment x así como add const to x

  • En el caso de n++, solo tendrá acceso a memoria 2 (leer n, inc n, escribir n)
  • En el caso de n=n+1, tendrá acceso a la memoria 3 (leer n, leer const, agregar n y const, escribir n)

Pero el compilador de hoy se convertirá automáticamente n=n+1 a ++n, y hará más de lo que puedas imaginar!!

También en los procesadores fuera de orden de hoy-a pesar del caso de "stone-age" compilador - el tiempo de ejecución puede no verse afectado en absoluto en muchos casos!!

Relacionado

 99
Author: Betamoo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:25:43

En GCC 4.4.3 para x86, con o sin optimizaciones, compilan exactamente el mismo código ensamblador, y por lo tanto toman la misma cantidad de tiempo para ejecutarse. Como puede ver en el ensamblado, GCC simplemente convierte n++ en n=n+1, luego lo optimiza en el complemento de una instrucción (en el-O2).

La sugerencia del instructor de que n++ es más rápido solo se aplica a compiladores muy antiguos que no optimizan, que no fueron lo suficientemente inteligentes como para seleccionar las instrucciones de actualización in situ para n = n + 1. Estos los compiladores han sido obsoletos en el mundo de las PC durante años, pero todavía se pueden encontrar para plataformas incrustadas propietarias extrañas.

Código C:

int n;

void nplusplus() {
    n++;
}

void nplusone() {
    n = n + 1;
}

Conjunto de salida (sin optimizaciones):

    .file   "test.c"
    .comm   n,4,4
    .text
.globl nplusplus
    .type   nplusplus, @function
nplusplus:
    pushl   %ebp
    movl    %esp, %ebp
    movl    n, %eax
    addl    $1, %eax
    movl    %eax, n
    popl    %ebp
    ret
    .size   nplusplus, .-nplusplus
.globl nplusone
    .type   nplusone, @function
nplusone:
    pushl   %ebp
    movl    %esp, %ebp
    movl    n, %eax
    addl    $1, %eax
    movl    %eax, n
    popl    %ebp
    ret
    .size   nplusone, .-nplusone
    .ident  "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3"
    .section    .note.GNU-stack,"",@progbits

Conjunto de salida (con optimizaciones-O2):

    .file   "test.c"
    .text
    .p2align 4,,15
.globl nplusplus
    .type   nplusplus, @function
nplusplus:
    pushl   %ebp
    movl    %esp, %ebp
    addl    $1, n
    popl    %ebp
    ret
    .size   nplusplus, .-nplusplus
    .p2align 4,,15
.globl nplusone
    .type   nplusone, @function
nplusone:
    pushl   %ebp
    movl    %esp, %ebp
    addl    $1, n
    popl    %ebp
    ret
    .size   nplusone, .-nplusone
    .comm   n,4,4
    .ident  "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3"
    .section    .note.GNU-stack,"",@progbits
 41
Author: bdonlan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-05-21 19:25:38

El compilador optimizará n + 1 en la nada.

¿Quieres decir n = n + 1?

Si es así, se compilarán en ensamblado idéntico. (Suponiendo que las optimizaciones están activadas y que son declaraciones, no expresiones)

 14
Author: SLaks,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-05-21 18:58:59

¿Quién dice que sí? Tu compilador lo optimiza todo, realmente, convirtiéndolo en un punto discutible.

 5
Author: Mahmoud Al-Qudsi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-05-21 18:58:48

Los compiladores modernos deberían ser capaces de reconocer ambos formularios como equivalentes y convertirlos al formato que mejor funcione en su plataforma de destino. Hay una excepción a esta regla: accesos variables que tienen efectos secundarios. Por ejemplo, si n es un registro de hardware mapeado en memoria, leer y escribir en él puede hacer más que simplemente transferir un valor de datos (leer puede borrar una interrupción, por ejemplo). Usarías la palabra clave volatile para que el compilador sepa que necesita tener cuidado con la optimización de accesos a n, y en ese caso el compilador podría generar código diferente de n++ (operación de incremento) y n = n + 1 (operaciones de lectura, adición y almacenamiento). Sin embargo, para variables normales, el compilador debe optimizar ambos formularios a la misma cosa.

 3
Author: bta,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-05-21 19:55:48

Realmente no. El compilador hará cambios específicos a la arquitectura de destino. Micro-optimizaciones como esta a menudo tienen dudosos beneficios, pero lo más importante, ciertamente no vale la pena el tiempo del programador.

 2
Author: Puppy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-05-21 19:09:48

En realidad, la razón es que el operador se define de manera diferente para post-fix que para pre-fix. ++n incrementará "n" y devolverá una referencia a "n" mientras que n++ incrementará "n" devolverá una copia const de "n". Por lo tanto, la frase n = n + 1 será más eficiente. Pero tengo que estar de acuerdo con los carteles anteriores. Los buenos compiladores deben optimizar un objeto de retorno no utilizado.

 2
Author: wheaties,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-05-21 19:32:41

En lenguaje C el efecto secundario de las expresiones n++ es por definición equivalente al efecto secundario de la expresión n = n + 1. Dado que su código se basa solo en los efectos secundarios, es inmediatamente obvio que la respuesta correcta es que estas expresiones siempre tienen un rendimiento exactamente equivalente. (Independientemente de cualquier configuración de optimización en el compilador, por cierto, ya que el problema no tiene absolutamente nada que ver con ninguna optimización.)

Cualquier divergencia práctica en el desempeño de estos expresiones solo es posible si el compilador es intencionalmente (y maliciosamente!) tratando de introducir esa divergencia. Pero en este caso puede ir de cualquier manera, por supuesto, es decir, de cualquier manera que el autor del compilador quería sesgar.

 2
Author: AnT,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-05-21 20:01:44

Creo que es más como una pregunta de hardware que de software... Si recuerdo correctamente, en CPU más antiguas el n = n + 1 requiere dos ubicaciones de memoria, donde el ++n es simplemente un comando de microcontrolador... Pero dudo que esto se aplique a las arquitecturas modernas...

 1
Author: Loupax,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-12-24 00:09:56

Todas esas cosas dependen de las directivas del compilador/procesador/compilación. Así que hacer cualquier suposición "lo que es más rápido en general" no es una buena idea.

 0
Author: Nickolay Olshevsky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-12-23 21:52:45