2017-06-03 32 views
9

Tek bir şamandıranın sarıldığı bir yapının, yaklaşık yüzdesiyle doğrudan bir şamandıra kullanmaktan çok daha yavaş olduğunu farkettim.Yapılandırmak için fazladan alan eklemek neden performansını büyük ölçüde artırıyor?

using System; 
using System.Diagnostics; 

struct Vector1 { 

    public float X; 

    public Vector1(float x) { 
     X = x; 
    } 

    public static Vector1 operator +(Vector1 a, Vector1 b) { 
     a.X = a.X + b.X; 
     return a; 
    } 
} 

Ancak ek 'ekstra' alanını ekleyerek üzerine, bazı sihir gibi görünüyor ve performans bir kez daha daha makul olur:

struct Vector1Magic { 

    public float X; 
    private bool magic; 

    public Vector1Magic(float x) { 
     X = x; 
     magic = true; 
    } 

    public static Vector1Magic operator +(Vector1Magic a, Vector1Magic b) { 
     a.X = a.X + b.X; 
     return a; 
    } 
} 

ben kriter için kullanılan kod, bu aşağıdaki gibidir:

kıyaslama sonuçlarla
class Program { 
    static void Main(string[] args) { 
     int iterationCount = 1000000000; 
     var sw = new Stopwatch(); 
     sw.Start(); 
     var total = 0.0f; 
     for (int i = 0; i < iterationCount; i++) { 
      var v = (float) i; 
      total = total + v; 
     } 
     sw.Stop(); 
     Console.WriteLine("Float time was {0} for {1} iterations.", sw.Elapsed, iterationCount); 
     Console.WriteLine("total = {0}", total); 
     sw.Reset(); 
     sw.Start(); 
     var totalV = new Vector1(0.0f); 
     for (int i = 0; i < iterationCount; i++) { 
      var v = new Vector1(i); 
      totalV += v; 
     } 
     sw.Stop(); 
     Console.WriteLine("Vector1 time was {0} for {1} iterations.", sw.Elapsed, iterationCount); 
     Console.WriteLine("totalV = {0}", totalV); 
     sw.Reset(); 
     sw.Start(); 
     var totalVm = new Vector1Magic(0.0f); 
     for (int i = 0; i < iterationCount; i++) { 
      var vm = new Vector1Magic(i); 
      totalVm += vm; 
     } 
     sw.Stop(); 
     Console.WriteLine("Vector1Magic time was {0} for {1} iterations.", sw.Elapsed, iterationCount); 
     Console.WriteLine("totalVm = {0}", totalVm); 
     Console.Read(); 
    } 
} 

:

Float time was 00:00:02.2444910 for 1000000000 iterations. 
Vector1 time was 00:00:04.4490656 for 1000000000 iterations. 
Vector1Magic time was 00:00:02.2262701 for 1000000000 iterations. 

Derleyici/çevre ayarları: OS: Windows 10 64 bit Toolchain: VS2017 Çerçevesi: Net 4.6.2 Hedef: 64 bit hedefi, sonuçlarımız olarak ayarlanır 32 bit

Eğer Herhangi bir CPU tercih https://pastebin.com/sz2QLGEx

: daha öngörülebilir, ancak 32 bit hedefte Vector1Magic ile gördüklerinizi daha kötü gibidir:, burada IL bir dökümünü gerçek sihirbazlar için

Float time was 00:00:00.6800014 for 1000000000 iterations. 
Vector1 time was 00:00:04.4572642 for 1000000000 iterations. 
Vector1Magic time was 00:00:05.7806399 for 1000000000 iterations. 

yer verdik Daha fazla araştırma, mono derleyicinin aynı IL'yi ürettiğinden, bunun Windows çalışma zamanına özgü olduğunu gösterir.

Mono çalışma zamanında, her iki yapı varyantı ham şamandıra ile karşılaştırıldığında kabaca 2x daha yavaş performansa sahiptir. Bu, gördüğümüz performansın biraz farklı. Net.

Neler oluyor burda?

* Bu sorunun başlangıçta hatalı bir değerlendirme süreci (bunu belirtmek için teşekkürler Max Payne) içerdiğini ve zamanlamaları daha doğru yansıtacak şekilde güncelleştirildiğini unutmayın.

+1

Im Bu şimdi daha iyi bellek hizalama sahip ambalaj yapılar nedeniyle tahmin:

7 yıl önce ansered yapıldığı anlaşılmaktadır. –

+2

JIT veya diğer tek seferlik işlemlerden kaynaklanan olası parazitleri hariç tutmak için bir ısınma iterasyonu eklemelisiniz. – PetSerAl

+2

64 bit'e geçersem, "sihirli" vektörünüz için daha kötü bir performans alırım. – Adrian

cevap

0

Bu olmamalıdır. Bu, JIT'i gerektiği gibi çalışmaya zorlayan bir tür yanlış hizalamadır.

struct Vector1 //Works fast in 32 Bit 
{ 
    public double X; 
} 

struct Vector1 //Works fast in 64 Bit and 32 Bit 
{ 
    public double X; 
    public double X2; 
} 

Ayrıca aramalıdır: Console.WriteLine (toplam);, zamanı tam olarak doğrulayan Vector1Magic zamanını arttırır. Soru hala Vector1'in neden bu kadar yavaş olduğunu gösteriyor.

Belki de yapılar struct() için uygun değil < 64 Bit 64 bit modunda. Why is 16 byte the recommended size for struct in C#?

+0

"Bu olmamalı. Bu, JIT'i gerektiği gibi çalışmamaya zorlayan bir tür yanlış hizalamadır." - Bu soruya gerçekten cevap vermiyor. Bu neden oluyor? Bunun arkasındaki mantık nedir? – Varon

+0

Daha sonra, birinin etrafına nasıl çalıştığını bilen bir kişi gelene kadar yukarı çıkış yapalım. Üretilen IL kodu iyidir, bu yüzden bizi çözüme ulaştırmayacak şekilde okuyun. Sorun, JIT iyileştiricinin içinde daha derindir. Bu çok ilginç bir keşif, belki bunu MSDN .net geliştirici-takım forumunda yayınlayabilirsin? –

+0

Lütfen Console.WriteLine (toplam) yazan bir satır ekleyin; ilk döngüsünden sonra. JIT, sonuçların daha sonra kullanılmadığı düğümleri yürütür. –

İlgili konular