Sembra che C# sia più veloce nell'aggiungere due array di UInt16[]
rispetto all'aggiunta di due array di int[]
. Questo non ha senso per me, dal momento che avrei pensato che gli array sarebbero stati allineati a parole, e quindi int[]
richiederebbe meno lavoro dalla CPU, no?Perché gli array UInt16 sembrano aggiungersi più velocemente degli array int?
ho eseguito il test-codice qui sotto, e ci hanno dato i seguenti risultati:
Int for 1000 took 9896625613 tick (4227 msec)
UInt16 for 1000 took 6297688551 tick (2689 msec)
Il codice di test esegue le seguenti operazioni:
- crea due array di nome
a
eb
, una volta. - Riempie con dati casuali una volta.
- Avvia un cronometro.
- Aggiunge
a
eb
, articolo per articolo. Questo è fatto 1000 volte. - Arresta il cronometro.
- Riporta quanto tempo è trascorso.
Questo viene fatto per int[] a, b
e per UInt16 a,b
. E ogni time eseguo il codice, i test per gli array UInt16
richiedono il 30% -50% di tempo in meno rispetto agli array int
. Puoi spiegarmelo?
Ecco il codice, se si vuole provare se voi stessi:
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)");
}
Hai provato a eseguire l'aggiunta di elementi inline, senza chiamare le funzioni AddXXX, passando e restituendo gli array? Hai provato altre dimensioni di array? –
@Grzegorz Gierlik: bella domanda. Così com'è, la routine 'int' probabilmente deve allocare il doppio della memoria. –
Che tipo di hardware è? Arrivo a 15650msec e 14657msec (leggi: nessuna differenza significativa). Sospetto che il microbenchmark ti stia buttando fuori - i motori JIT e le VM ottimizzatrici sono famosi per questo. La velocità di aggiunta dei numeri (16/32 bit) * sarà la stessa * su qualsiasi CPU x86/x64 moderna. Tuttavia, numeri più grandi possono comportare una piccola penalità in termini di riempimento di più linee di cache e possibilmente richiedendo più bus da trasferire. –