c performance optimization modulo

¿es mejor evitar usar el operador de mod cuando sea posible?



performance optimization (3)

Supongo que calcular el módulo de un número es una operación algo costosa, al menos en comparación con las pruebas aritméticas simples (como ver si un número excede la longitud de una matriz). Si este es realmente el caso, ¿es más eficiente reemplazar, por ejemplo, el siguiente código?

res = array[(i + 1) % len];

¿con lo siguiente? :

res = array[(i + 1 == len) ? 0 : i + 1];

El primero es más fácil para los ojos, pero me pregunto si el segundo podría ser más eficiente. Si es así, ¿podría esperar que un compilador de optimización reemplace el primer fragmento con el segundo cuando se usa un lenguaje compilado?

Por supuesto, esta "optimización" (si se trata de una optimización) no funciona en todos los casos (en este caso, solo funciona si i+1 nunca es más que len ).


Algunas medidas simples:

#include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { int test = atoi(argv[1]); int divisor = atoi(argv[2]); int iterations = atoi(argv[3]); int a = 0; if (test == 0) { for (int i = 0; i < iterations; i++) a = (a + 1) % divisor; } else if (test == 1) { for (int i = 0; i < iterations; i++) a = a + 1 == divisor ? 0 : a + 1; } printf("%d/n", a); }

Compilando con gcc o clang con -O3 , y time ./a.out 0 42 1000000000 ejecución time ./a.out 0 42 1000000000 (versión de módulo) o time ./a.out 1 42 1000000000 (versión de comparación) da como resultado

  • 6.25 segundos de tiempo de ejecución del usuario para la versión del módulo,
  • 1.03 segundos para la versión de comparación.

(utilizando gcc 5.2.1 o clang 3.6.2; Intel Core i5-4690K a 3.50 GHz; Linux de 64 bits)

Esto significa que probablemente sea una buena idea usar la versión de comparación.


Mi consejo general es el siguiente. Utilice la versión que crea más fácil para el ojo y luego perfile todo su sistema. Solo optimice aquellas partes del código que el perfilador señala como cuellos de botella. Apostaría mi último dólar a que el operador del módulo no va a estar entre ellos.

En cuanto al ejemplo específico, solo el benchmarking puede decir cuál es más rápido en su arquitectura específica usando su compilador específico. Usted está reemplazando potencialmente módulo con branching , y es cualquier cosa menos obvio que sería más rápido.


Modulo se puede hacer con una sola instrucción de procesador en la mayoría de las arquitecturas (por ejemplo, DIV en x86). Sin embargo, es probable que sea una optimización prematura de lo que necesita.