2010-02-10 12 views
5

Me preguntaba si este es el comportamiento esperado en C++. El código siguiente funciona a alrededor de 0,001 ms:Escritura lenta en una matriz en C++

for(int l=0;l<100000;l++){ 
     int total=0; 
     for(int i = 0; i < num_elements; i++) 
     { 
      total+=i; 
     } 
    } 

Sin embargo, si los resultados se escriben en una matriz, el tiempo de ejecución se dispara a 15 ms:

int *values=(int*)malloc(sizeof(int)*100000); 
     for(int l=0;l<100000;l++){ 
      int total=0; 
      for(unsigned int i = 0; i < num_elements; i++) 
      { 
       total+=i; 
      } 
      values[l]=total; 
     } 

puedo apreciar que la escritura a la la matriz lleva tiempo pero ¿es proporcional el tiempo?

todos aplauden

+0

Su pregunta dice C, pero sus etiquetas dicen C++. ¿Cuál es? –

+0

lo siento, estrictamente C++ pero si las declaraciones int se movieron fuera de los ciclos for entonces C – Ljdawson

+0

@Laurence - No, su código es perfectamente estándar en C99, y la mayoría de los compiladores C89 aceptarán la sintaxis que use. –

Respuesta

11

El primer ejemplo se puede implementar utilizando solo registros de la CPU. Se puede acceder a esos miles de millones de veces por segundo. El segundo ejemplo usa tanta memoria que ciertamente desborda L1 y posiblemente L2 caché (dependiendo del modelo de CPU). Eso será más lento. Aún así, 15 ms/100.000 escrituras salen a 1.5 ns por escritura - 667 Mhz efectivamente. Eso es no lento.

+1

+1 para señalar los registros de la CPU. En el segundo caso, el código avanza por la memoria, escribe bytes (tirando de páginas de memoria, forzando cachés a enjuagar, ... luego escribe solo un valor). En el primer caso, puede ser fácilmente puro L1. Esta respuesta debería ser más votada. – anon

+0

excelente respuesta, gracias – Ljdawson

10

Parece que el compilador es la optimización de ese bucle a cabo en su totalidad en el primer caso.

El efecto total del ciclo no es operativo, por lo que el compilador simplemente lo elimina.

+0

aha! Pensé lo mismo, ¿hay alguna manera de desactivar esta optimización para el benchmarking o es eso? – Ljdawson

+0

En gran medida, depende del compilador y del IDE que esté utilizando. Consulte la página del archivo de ayuda/manual para ver lo que debe hacer para deshabilitar las optimizaciones. –

+1

intente usar el total después del ciclo; o agregue -O0 si está usando gcc. – tristan

1

Sospecho que lo que está viendo es un efecto de virtual memory y posiblemente de paginación. La llamada malloc va a asignar un trozo de memoria de tamaño decente que probablemente esté representado por un número de páginas virtuales. Cada página está vinculada a la memoria de proceso por separado.

También puede estar midiendo el costo de llamar al malloc dependiendo de cómo haya sincronizado el ciclo. En cualquier caso, el rendimiento va a ser muy sensible a las opciones de optimización del compilador, las opciones de subprocesamiento, las versiones de compilación, las versiones de tiempo de ejecución y casi cualquier otra cosa. No puede suponer con seguridad que el costo es lineal con el tamaño de la asignación. Lo único que puede hacer es medirlo y averiguar cómo optimizar mejor una vez que se ha demostrado que es un problema.

3

Es muy simple. En el primer caso Tiene solo 3 variables, que pueden almacenarse fácilmente en GPR (registros de propósito general), pero eso no significa que estén ahí todo el tiempo, pero probablemente estén en la memoria caché L1, lo que significa que se puede acceder muy rápido.

En el segundo caso Tiene más de 100k variables, y necesita aproximadamente 400kB para almacenarlas. Eso es sin duda demasiado para los registros y la memoria caché L1. En el mejor de los casos, podría estar en la memoria caché L2, pero probablemente no todos estarán en L2. Si algo no está registrado, L1, L2 (supongo que su procesador no tiene L3) significa que necesita buscarlo en la memoria RAM y le lleva mucho más tiempo.