SORU
7 AĞUSTOS 2015, Cuma


Büyük performans 32 ve 64 bit için derlerken fark (26x daha hızlı)

for ve değeri foreach zaman erişim listeleri türleri ve referans türleri kullanarak farkı ölçmek için çalışıyordum.

Aşağıdaki sınıf profilleme yapmak için kullandım.

public static class Benchmarker
{
    public static void Profile(string description, int iterations, Action func)
    {
        Console.Write(description);

        // Warm up
        func();

        Stopwatch watch = new Stopwatch();

        // Clean up
        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.Collect();

        watch.Start();
        for (int i = 0; i < iterations; i  )
        {
            func();
        }
        watch.Stop();

        Console.WriteLine(" average time: {0} ms", watch.Elapsed.TotalMilliseconds / iterations);
    }
}

Benim değer türü için double kullandım. Ve bunu ben yarattım 'sahte sınıf test referans türleri için:

class DoubleWrapper
{
    public double Value { get; set; }

    public DoubleWrapper(double value)
    {
        Value = value;
    }
}

Son olarak bu kodu araştırdım ve zaman farklılıkları karşılaştırdı.

static void Main(string[] args)
{
    int size = 1000000;
    int iterationCount = 100;

    var valueList = new List<double>(size);
    for (int i = 0; i < size; i  ) 
        valueList.Add(i);

    var refList = new List<DoubleWrapper>(size);
    for (int i = 0; i < size; i  ) 
        refList.Add(new DoubleWrapper(i));

    double dummy;

    Benchmarker.Profile("valueList for: ", iterationCount, () =>
    {
        double result = 0;
        for (int i = 0; i < valueList.Count; i  )
        {
             unchecked
             {
                 var temp = valueList[i];
                 result *= temp;
                 result  = temp;
                 result /= temp;
                 result -= temp;
             }
        }
        dummy = result;
    });

    Benchmarker.Profile("valueList foreach: ", iterationCount, () =>
    {
        double result = 0;
        foreach (var v in valueList)
        {
            var temp = v;
            result *= temp;
            result  = temp;
            result /= temp;
            result -= temp;
        }
        dummy = result;
    });

    Benchmarker.Profile("refList for: ", iterationCount, () =>
    {
        double result = 0;
        for (int i = 0; i < refList.Count; i  )
        {
            unchecked
            {
                var temp = refList[i].Value;
                result *= temp;
                result  = temp;
                result /= temp;
                result -= temp;
            }
        }
        dummy = result;
    });

    Benchmarker.Profile("refList foreach: ", iterationCount, () =>
    {
        double result = 0;
        foreach (var v in refList)
        {
            unchecked
            {
                var temp = v.Value;
                result *= temp;
                result  = temp;
                result /= temp;
                result -= temp;
            }
        }

        dummy = result;
    });

    SafeExit();
}

Release Any CPU seçenekleri seçtim, programı koştu ve aşağıdaki zamanları var:

valueList for:  average time: 483,967938 ms
valueList foreach:  average time: 477,873079 ms
refList for:  average time: 490,524197 ms
refList foreach:  average time: 485,659557 ms
Done!

Sonra Bırakın ve 64 seçenekleri seçtim, programı koştu ve aşağıdaki zamanları var:

valueList for:  average time: 16,720209 ms
valueList foreach:  average time: 15,953483 ms
refList for:  average time: 19,381077 ms
refList foreach:  average time: 18,636781 ms
Done!

Neden 64 bit sürümü çok daha hızlı? Bir fark, ama bu büyük birşey değil beklediğim.

Diğer bilgisayarlara erişimi yok. Sizin makinelerde bu çalışma ve sonuçları bana söyler misiniz? Bir istihbaratım var 2015 ve Visual Studio kullanıyorum Core i7 930.

Burada SafeExit() yöntemin,/kendiniz çalıştırın derlemek, böylece:

private static void SafeExit()
{
    Console.WriteLine("Done!");
    Console.ReadLine();
    System.Environment.Exit(1);
}

Olarak, DoubleWrapper benim: yerine double? kullanma talebinde bulundu

Herhangi bir CPU

valueList for:  average time: 482,98116 ms
valueList foreach:  average time: 478,837701 ms
refList for:  average time: 491,075915 ms
refList foreach:  average time: 483,206072 ms
Done!

64

valueList for:  average time: 16,393947 ms
valueList foreach:  average time: 15,87007 ms
refList for:  average time: 18,267736 ms
refList foreach:  average time: 16,496038 ms
Done!

Son ama en az değil: x86 profil oluşturma Any CPU kullanarak hemen hemen aynı sonuçları verir.

CEVAP
7 AĞUSTOS 2015, Cuma


4.5.2 bu çoğaltabilir. Hayır burada RyuJİT. Hem x 86 ve x 64 disassemblies makul görünüyor. Çekler aralığı ve aynıdır. Aynı temel yapısı. Hayır döngü çözümü.

86 şamandıra talimatları farklı bir dizi kullanır. Bu talimatları performansı x 64 talimatları ile karşılaştırılabilir gibi görünüyorbölümü hariç:

  1. The 32 bit x87 float instructions use 10 byte precision internally.
  2. Extended precision division is super slow.

Bölme işlemi 32 bit sürümü çok yavaş olur.Bölüm Uncommenting performans olarak gelişirbüyük ölçüde (32 bit 3.25 ms 430ms aşağı).

Peter Cordes iki kayan nokta birimlerinin öğretim gecikmeleri olmayan farklı olduğuna dikkat çekiyor. Belki bazı Ara sonuçlara normal dışı sayıları ya NaN. Bu birimlerden biri yavaş bir yolu tetikleyebilir. Ya da, değerleri iki uygulamaları arasındaki farklılık 10 byte vs 8 bayt şamandıra hassas yüzünden belki de.

Peter also points out that all intermediate results are NaN... Bu sorun (bölen sıfır olacak şekildevalueList.Add(i 1)) Kaldırma Cordes sonuçlar oluşur çoğunlukla. Görünüşe göre, 32 bit kod NaN işlenen hiç sevmez. Hadi baskı bazı Ara değerler: if (i % 1000 == 0) Console.WriteLine(result);. Bu veriler şimdi aklı başında olduğunu gösteriyor.

Gerçekçi bir iş yükü kriter için gereken kıyaslama. Ama masum bir bölümü senin kriter karışıklık olduğunu kim düşünebilirdi?!

Sadece bir sayı daha iyi bir referans almak için toplamak deneyin.

Bölümü ve modül her zaman çok yavaş. Dictionary kod KORUYUCU sadece modül operatörü kova dizin hesaplamak için kullanmak için değil değiştirirseniz performans ölçülebilir geliştirir. Bu yavaş bölümüdür.

İşte 32 bit kodu:

enter image description here

64 bit kod (aynı yapı, hızlı bölümü):

enter image description here

BudeğilSSE talimatları kullanılmış olmasına rağmen vectorized.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Lin Steven

    Lin Steven

    17 EKİM 2006
  • Madeon

    Madeon

    31 Ocak 2010
  • xXGAMERrs_Xx

    xXGAMERrs_Xx

    31 Temmuz 2014