He estado haciendo algunas pruebas de rendimiento, principalmente para poder entender la diferencia entre iteradores y bucles simples. Como parte de esto, creé un conjunto simple de pruebas y luego me sorprendieron por completo los resultados. Para algunos métodos, 64 bits era casi 10 veces más rápido que 32 bits.¿Por qué es esto más rápido en 64 bit que en 32 bit?
Lo que estoy buscando es una explicación de por qué esto está sucediendo.
[La respuesta a continuación indica que esto se debe a la aritmética de 64 bits en una aplicación de 32 bits. El cambio de longs a ints da como resultado un buen rendimiento en sistemas de 32 y 64 bits.]
Aquí están los 3 métodos en cuestión.
private static long ForSumArray(long[] array)
{
var result = 0L;
for (var i = 0L; i < array.LongLength; i++)
{
result += array[i];
}
return result;
}
private static long ForSumArray2(long[] array)
{
var length = array.LongLength;
var result = 0L;
for (var i = 0L; i < length; i++)
{
result += array[i];
}
return result;
}
private static long IterSumArray(long[] array)
{
var result = 0L;
foreach (var entry in array)
{
result += entry;
}
return result;
}
que tienen un simple instrumento de prueba que pone a prueba esta
var repeat = 10000;
var arrayLength = 100000;
var array = new long[arrayLength];
for (var i = 0; i < arrayLength; i++)
{
array[i] = i;
}
Console.WriteLine("For: {0}", AverageRunTime(repeat,() => ForSumArray(array)));
repeat = 100000;
Console.WriteLine("For2: {0}", AverageRunTime(repeat,() => ForSumArray2(array)));
Console.WriteLine("Iter: {0}", AverageRunTime(repeat,() => IterSumArray(array)));
private static TimeSpan AverageRunTime(int count, Action method)
{
var stopwatch = new Stopwatch();
stopwatch.Start();
for (var i = 0; i < count; i++)
{
method();
}
stopwatch.Stop();
var average = stopwatch.Elapsed.Ticks/count;
return new TimeSpan(average);
}
Cuando corro éstos, consigo los siguientes resultados:
32 bits:
For: 00:00:00.0006080 For2: 00:00:00.0005694 Iter: 00:00:00.0001717
64 bits
For: 00:00:00.0007421 For2: 00:00:00.0000814 Iter: 00:00:00.0000818
Lo que leo de esto es que usar LongLength es lento. Si uso array.Length, el rendimiento para el primer ciclo for es bastante bueno en 64 bits, pero no en 32 bits.
La otra cosa que leí de esto es que iterar en una matriz es tan eficiente como un ciclo for, ¡y el código es mucho más limpio y fácil de leer!
Lo que también me parece interesante es que, obviamente, el compilador JIT no optimiza el acceso array.LongLength. – newgre