Parece que C# es más rápido al agregar dos matrices de UInt16[]
que al agregar dos matrices de int[]
. Esto no tiene sentido para mí, ya que habría asumido que las matrices estarían alineadas con palabras, y por lo tanto int[]
requeriría menos trabajo de la CPU, ¿no?¿Por qué las matrices UInt16 parecen agregar más rápido que las matrices en línea?
que corrió la prueba de código a continuación, y tiene los siguientes resultados:
Int for 1000 took 9896625613 tick (4227 msec)
UInt16 for 1000 took 6297688551 tick (2689 msec)
El código de prueba hace lo siguiente:
- crea dos matrices nombradas
a
yb
, una vez. - Los llena con datos aleatorios, una vez.
- Inicia un cronómetro.
- Agrega
a
yb
, artículo por elemento. Esto se hace 1000 veces. - Detiene el cronómetro.
- Informa cuánto tiempo tomó.
Esto se hace para int[] a, b
y para UInt16 a,b
. Y cada vez que ejecuto el código, las pruebas para las matrices UInt16
tardan entre un 30% y un 50% menos de tiempo que las matrices int
. Me puedes explicar esto?
Aquí está el código, si quieres probar si usted mismo:
public static UInt16[] GenerateRandomDataUInt16(int length)
{
UInt16[] noise = new UInt16[length];
Random random = new Random((int)DateTime.Now.Ticks);
for (int i = 0; i < length; ++i)
{
noise[i] = (UInt16)random.Next();
}
return noise;
}
public static int[] GenerateRandomDataInt(int length)
{
int[] noise = new int[length];
Random random = new Random((int)DateTime.Now.Ticks);
for (int i = 0; i < length; ++i)
{
noise[i] = (int)random.Next();
}
return noise;
}
public static int[] AddInt(int[] a, int[] b)
{
int len = a.Length;
int[] result = new int[len];
for (int i = 0; i < len; ++i)
{
result[i] = (int)(a[i] + b[i]);
}
return result;
}
public static UInt16[] AddUInt16(UInt16[] a, UInt16[] b)
{
int len = a.Length;
UInt16[] result = new UInt16[len];
for (int i = 0; i < len; ++i)
{
result[i] = (ushort)(a[i] + b[i]);
}
return result;
}
public static void Main()
{
int count = 1000;
int len = 128 * 6000;
int[] aInt = GenerateRandomDataInt(len);
int[] bInt = GenerateRandomDataInt(len);
Stopwatch s = new Stopwatch();
s.Start();
for (int i=0; i<count; ++i)
{
int[] resultInt = AddInt(aInt, bInt);
}
s.Stop();
Console.WriteLine("Int for " + count
+ " took " + s.ElapsedTicks + " tick ("
+ s.ElapsedMilliseconds + " msec)");
UInt16[] aUInt16 = GenerateRandomDataUInt16(len);
UInt16[] bUInt16 = GenerateRandomDataUInt16(len);
s = new Stopwatch();
s.Start();
for (int i=0; i<count; ++i)
{
UInt16[] resultUInt16 = AddUInt16(aUInt16, bUInt16);
}
s.Stop();
Console.WriteLine("UInt16 for " + count
+ " took " + s.ElapsedTicks + " tick ("
+ s.ElapsedMilliseconds + " msec)");
}
¿trató de ejecutar la adición de elementos en línea - sin llamar funciones AddXXX, pasando y volviendo matrices? ¿Has probado otro tamaño de matrices? –
@Grzegorz Gierlik: buena pregunta de hecho. Tal como está, la rutina 'int' probablemente tenga que asignar el doble de memoria. –
¿Qué hardware es eso? Llego a 15650 mseg y 14657 mseg (léase: sin diferencia significativa). Sospecho que el microbenchmark te está desanimando: los motores JIT y la optimización de máquinas virtuales son notorios por eso. La velocidad de adición de los números (16/32 bit) * será la misma * en cualquier CPU x86/x64 moderna. Sin embargo, números más grandes pueden tener una pequeña penalización en términos de llenar más líneas de caché y posiblemente requieran más buses para transferir. –