Ponieważ miałem podobne pytanie, zapewniłem sobie szybki start.
Moje pytanie jest nieco bardziej szczegółowe: „jaka jest najszybsza metoda implementacji macierzy zwrotnej”
Testy przeprowadzone przez Marca Gravella pokazują wiele, ale nie dokładnie określają czas. Jego wyczucie czasu obejmuje również zapętlanie tablicy i list. Ponieważ wymyśliłem także trzecią metodę, którą chciałem przetestować, czyli „Słownik”, dla porównania, rozszerzyłem kod testowy hist.
Najpierw wykonuję test przy użyciu stałej, która daje mi pewien czas, w tym pętlę. Jest to czas „goły”, z wyłączeniem faktycznego dostępu. Następnie wykonuję test, uzyskując dostęp do struktury tematu, co daje mi i taktowanie, zapętlenie i rzeczywisty dostęp.
Różnica między taktowaniem „nagim” a czasem „wykluczonym z góry” daje mi wskazanie taktowania „dostępu do struktury”.
Ale jak dokładny jest ten czas? Podczas testu Windows wykona krojenie czasu dla shure. Nie mam żadnych informacji na temat podziału czasu, ale zakładam, że jest on równomiernie rozłożony podczas testu i rzędu dziesiątek ms, co oznacza, że dokładność pomiaru czasu powinna być rzędu +/- 100 ms lub więcej. Trochę przybliżone oszacowanie? W każdym razie źródło systematycznego błędu mearure.
Ponadto testy przeprowadzono w trybie „Debugowanie” bez optymalizacji. W przeciwnym razie kompilator może zmienić rzeczywisty kod testowy.
Otrzymuję więc dwa wyniki, jeden dla stałej oznaczonej „(c)”, a drugi dla dostępu oznaczony „(n)”, a różnica „dt” mówi mi, ile czasu zajmuje faktyczny dostęp.
A oto wyniki:
Dictionary(c)/for: 1205ms (600000000)
Dictionary(n)/for: 8046ms (589725196)
dt = 6841
List(c)/for: 1186ms (1189725196)
List(n)/for: 2475ms (1779450392)
dt = 1289
Array(c)/for: 1019ms (600000000)
Array(n)/for: 1266ms (589725196)
dt = 247
Dictionary[key](c)/foreach: 2738ms (600000000)
Dictionary[key](n)/foreach: 10017ms (589725196)
dt = 7279
List(c)/foreach: 2480ms (600000000)
List(n)/foreach: 2658ms (589725196)
dt = 178
Array(c)/foreach: 1300ms (600000000)
Array(n)/foreach: 1592ms (589725196)
dt = 292
dt +/-.1 sec for foreach
Dictionary 6.8 7.3
List 1.3 0.2
Array 0.2 0.3
Same test, different system:
dt +/- .1 sec for foreach
Dictionary 14.4 12.0
List 1.7 0.1
Array 0.5 0.7
Przy lepszych oszacowaniach błędów synchronizacji (jak usunąć systematyczny błąd pomiaru z powodu podziału czasu?) Można by powiedzieć więcej o wynikach.
Wygląda na to, że Lista / Foreach ma najszybszy dostęp, ale koszty ogólne go zabijają.
Różnica między List / for i List / foreach jest dziwna. Może w grę wchodzi gotówka?
Ponadto, aby uzyskać dostęp do tablicy, nie ma znaczenia, czy używasz for
pętli czy foreach
pętli. Wyniki pomiaru czasu i jego dokładność sprawiają, że wyniki są „porównywalne”.
Korzystanie ze słownika jest zdecydowanie najwolniejsze, zastanawiałem się tylko nad tym, ponieważ po lewej stronie (indeksator) mam rzadką listę liczb całkowitych, a nie zakres używany w tych testach.
Oto zmodyfikowany kod testowy.
Dictionary<int, int> dict = new Dictionary<int, int>(6000000);
List<int> list = new List<int>(6000000);
Random rand = new Random(12345);
for (int i = 0; i < 6000000; i++)
{
int n = rand.Next(5000);
dict.Add(i, n);
list.Add(n);
}
int[] arr = list.ToArray();
int chk = 0;
Stopwatch watch = Stopwatch.StartNew();
for (int rpt = 0; rpt < 100; rpt++)
{
int len = dict.Count;
for (int i = 0; i < len; i++)
{
chk += 1; // dict[i];
}
}
watch.Stop();
long c_dt = watch.ElapsedMilliseconds;
Console.WriteLine(" Dictionary(c)/for: {0}ms ({1})", c_dt, chk);
chk = 0;
watch = Stopwatch.StartNew();
for (int rpt = 0; rpt < 100; rpt++)
{
int len = dict.Count;
for (int i = 0; i < len; i++)
{
chk += dict[i];
}
}
watch.Stop();
long n_dt = watch.ElapsedMilliseconds;
Console.WriteLine(" Dictionary(n)/for: {0}ms ({1})", n_dt, chk);
Console.WriteLine("dt = {0}", n_dt - c_dt);
watch = Stopwatch.StartNew();
for (int rpt = 0; rpt < 100; rpt++)
{
int len = list.Count;
for (int i = 0; i < len; i++)
{
chk += 1; // list[i];
}
}
watch.Stop();
c_dt = watch.ElapsedMilliseconds;
Console.WriteLine(" List(c)/for: {0}ms ({1})", c_dt, chk);
watch = Stopwatch.StartNew();
for (int rpt = 0; rpt < 100; rpt++)
{
int len = list.Count;
for (int i = 0; i < len; i++)
{
chk += list[i];
}
}
watch.Stop();
n_dt = watch.ElapsedMilliseconds;
Console.WriteLine(" List(n)/for: {0}ms ({1})", n_dt, chk);
Console.WriteLine("dt = {0}", n_dt - c_dt);
chk = 0;
watch = Stopwatch.StartNew();
for (int rpt = 0; rpt < 100; rpt++)
{
for (int i = 0; i < arr.Length; i++)
{
chk += 1; // arr[i];
}
}
watch.Stop();
c_dt = watch.ElapsedMilliseconds;
Console.WriteLine(" Array(c)/for: {0}ms ({1})", c_dt, chk);
chk = 0;
watch = Stopwatch.StartNew();
for (int rpt = 0; rpt < 100; rpt++)
{
for (int i = 0; i < arr.Length; i++)
{
chk += arr[i];
}
}
watch.Stop();
n_dt = watch.ElapsedMilliseconds;
Console.WriteLine("Array(n)/for: {0}ms ({1})", n_dt, chk);
Console.WriteLine("dt = {0}", n_dt - c_dt);
chk = 0;
watch = Stopwatch.StartNew();
for (int rpt = 0; rpt < 100; rpt++)
{
foreach (int i in dict.Keys)
{
chk += 1; // dict[i]; ;
}
}
watch.Stop();
c_dt = watch.ElapsedMilliseconds;
Console.WriteLine("Dictionary[key](c)/foreach: {0}ms ({1})", c_dt, chk);
chk = 0;
watch = Stopwatch.StartNew();
for (int rpt = 0; rpt < 100; rpt++)
{
foreach (int i in dict.Keys)
{
chk += dict[i]; ;
}
}
watch.Stop();
n_dt = watch.ElapsedMilliseconds;
Console.WriteLine("Dictionary[key](n)/foreach: {0}ms ({1})", n_dt, chk);
Console.WriteLine("dt = {0}", n_dt - c_dt);
chk = 0;
watch = Stopwatch.StartNew();
for (int rpt = 0; rpt < 100; rpt++)
{
foreach (int i in list)
{
chk += 1; // i;
}
}
watch.Stop();
c_dt = watch.ElapsedMilliseconds;
Console.WriteLine(" List(c)/foreach: {0}ms ({1})", c_dt, chk);
chk = 0;
watch = Stopwatch.StartNew();
for (int rpt = 0; rpt < 100; rpt++)
{
foreach (int i in list)
{
chk += i;
}
}
watch.Stop();
n_dt = watch.ElapsedMilliseconds;
Console.WriteLine(" List(n)/foreach: {0}ms ({1})", n_dt, chk);
Console.WriteLine("dt = {0}", n_dt - c_dt);
chk = 0;
watch = Stopwatch.StartNew();
for (int rpt = 0; rpt < 100; rpt++)
{
foreach (int i in arr)
{
chk += 1; // i;
}
}
watch.Stop();
c_dt = watch.ElapsedMilliseconds;
Console.WriteLine(" Array(c)/foreach: {0}ms ({1})", c_dt, chk);
chk = 0;
watch = Stopwatch.StartNew();
for (int rpt = 0; rpt < 100; rpt++)
{
foreach (int i in arr)
{
chk += i;
}
}
watch.Stop();
n_dt = watch.ElapsedMilliseconds;
Console.WriteLine("Array(n)/foreach: {0}ms ({1})", n_dt, chk);
Console.WriteLine("dt = {0}", n_dt - c_dt);