C # vs C - Büyük performans farkı


94

C ve C #'daki benzer kodlar arasında büyük performans farklılıkları buluyorum.

C kodu:

#include <stdio.h>
#include <time.h>
#include <math.h>

main()
{
    int i;
    double root;

    clock_t start = clock();
    for (i = 0 ; i <= 100000000; i++){
        root = sqrt(i);
    }
    printf("Time elapsed: %f\n", ((double)clock() - start) / CLOCKS_PER_SEC);   

}

Ve C # (konsol uygulaması):

using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            DateTime startTime = DateTime.Now;
            double root;
            for (int i = 0; i <= 100000000; i++)
            {
                root = Math.Sqrt(i);
            }
            TimeSpan runTime = DateTime.Now - startTime;
            Console.WriteLine("Time elapsed: " + Convert.ToString(runTime.TotalMilliseconds/1000));
        }
    }
}

Yukarıdaki kodla, C # 0.328125 saniyede tamamlanır (yayın sürümü) ve C'nin çalışması 11.14 saniye sürer.

C, mingw kullanılarak çalıştırılabilir bir pencerede derleniyor.

Her zaman C / C ++ 'nın daha hızlı veya en azından C # .net ile karşılaştırılabilir olduğu varsayımındayım. C'nin 30 kat daha yavaş çalışmasına tam olarak ne sebep oluyor?

DÜZENLEME: Görünüşe göre C # optimize edici, kullanılmadığı için kökü kaldırıyordu. Kök atamasını kök + = olarak değiştirdim ve sonunda toplamı yazdırdım. Ayrıca, maksimum hız için ayarlanmış / O2 bayrağıyla cl.exe kullanarak C'yi derledim.

Sonuçlar şimdi: C için 3,75 saniye C # için 2,61 saniye

C hala daha uzun sürüyor, ancak bu kabul edilebilir


19
Sadece bir DateTime yerine bir StopWatch kullanmanızı öneririm.
Alex Fort

2
Hangi derleyici bayrakları? Her ikisi de optimizasyon etkinleştirilerek derlendi mi?
jalf

2
C ++ derleyicisiyle -ffast-math kullandığınızda ne olacak?
Dan McClain

10
Ne kadar büyüleyici bir soru!
Robert S.

4
Belki C sqrt işlevi C # 'da bu kadar iyi değildir. O zaman C ile ilgili bir sorun olmazdı, ona kütüphane eklenmişti. Matematik fonksiyonları olmadan bazı hesaplamaları deneyin.
klew

Yanıtlar:


61

Asla 'root' kullanmadığınız için, derleyici yönteminizi optimize etmek için çağrıyı kaldırıyor olabilir.

Karekök değerlerini bir toplayıcıda toplamayı deneyebilir, yöntemin sonunda yazdırabilir ve neler olduğunu görebilirsiniz.

Düzenleme: Jalf'ın aşağıdaki cevabına bakın


1
Küçük bir deney, durumun böyle olmadığını gösteriyor. Döngünün kodu üretilir, ancak çalışma zamanı onu atlayacak kadar akıllı olabilir. Biriktirilse bile, C # hala C'nin pantolonunu yeniyor
Dana

3
Görünüşe göre sorun diğer tarafta. C # her durumda makul davranır. Görünüşe göre C kodu optimizasyon yapılmadan derlenmiş
jalf

2
Çoğunuz buradaki noktayı kaçırıyorsunuz. C # 'nin c / c ++' dan daha iyi performans gösterdiği ve her zaman çürütmenin bazı uzman düzeyinde optimizasyon kullanmak olduğu birçok benzer durum okudum. Programcıların% 99'u, kodlarının c # kodundan biraz daha hızlı çalışmasını sağlamak için bu tür optimizasyon tekniklerini kullanma bilgisine sahip değil. C / c ++ için kullanım durumları daralmaktadır.

167

Hata ayıklama yapılarını karşılaştırmalısınız. C kodunuzu derledim ve

Time elapsed: 0.000000

Optimizasyonları etkinleştirmezseniz, yaptığınız herhangi bir kıyaslama tamamen değersizdir. (Ve optimizasyonları etkinleştirirseniz, döngü optimize edilir. Dolayısıyla, kıyaslama kodunuz da kusurludur. Genellikle sonucu veya benzerini toplayıp sonunda yazdırarak döngüyü çalıştırmaya zorlamanız gerekir)

Görünüşe göre ölçtüğünüz şey temelde "hangi derleyici en fazla hata ayıklama ek yükünü ekliyor". Ve cevabın C olduğu ortaya çıktı. Ama bu bize hangi programın en hızlı olduğunu söylemez. Çünkü hız istediğinizde optimizasyonları etkinleştirirsiniz.

Bu arada, dillerin birbirinden "daha hızlı" olduğu fikrinden vazgeçerseniz, uzun vadede baş ağrısından kurtulacaksınız. C # artık İngilizce'den daha hızlı değil.

C dilinde optimizasyon yapmayan naif bir derleyicide bile verimli olabilecek bazı şeyler vardır ve her şeyi optimize etmek için büyük ölçüde bir derleyiciye güvenen başka şeyler de vardır. Ve tabii ki aynı şey C # veya başka bir dil için de geçerli.

Yürütme hızı aşağıdakilere göre belirlenir:

  • çalıştırdığınız platform (işletim sistemi, donanım, sistemde çalışan diğer yazılımlar)
  • derleyici
  • kaynak kodunuz

İyi bir C # derleyicisi verimli kod üretecektir. Kötü bir C derleyicisi yavaş kod üretecektir. C # kodunu oluşturan ve daha sonra bir C # derleyicisinden çalıştırabileceğiniz bir C derleyicisine ne dersiniz? Bu ne kadar hızlı koşar? Dillerin hızı yok. Kodunuz var.



18
Güzel cevap, ama en azından benzetme olarak dil hızı konusunda aynı fikirde değilim: Welsch'in uzun ünlülerin yüksek frekansı nedeniyle çoğundan daha yavaş bir dil olduğu bulundu. Ek olarak, insanlar daha hızlı söylerlerse kelimeleri (ve kelime listelerini) daha iyi hatırlar. web.missouri.edu/~cowann/docs/articles/before%201993/… en.wikipedia.org/wiki/Vowel_length en.wikipedia.org/wiki/Welsh_language
exceptionerror

1
Bu , Welsch'te ne söylediğine bağlı değil mi? Her şeyin daha yavaş olmasını pek olası bulmuyorum .
jalf

5
++ Hey millet, burada dikkatinizi dağıtmayın. Aynı program bir dilde diğerinden daha hızlı çalışıyorsa, bunun nedeni farklı derleme kodunun üretilmesidir. Bu özel örnekte, zamanın% 99'u veya daha fazlası yüzmeye gidecek ive sqrtbu yüzden ölçülen şey bu.
Mike Dunlavey

116

Kısa tutacağım, zaten cevaplandı olarak işaretlendi. C #, iyi tanımlanmış bir kayan nokta modeline sahip olmanın büyük avantajına sahiptir. Bu, x86 ve x64 işlemcilerdeki FPU ve SSE komut kümesinin yerel işlem moduyla eşleşiyor. Orada tesadüf yok. JITter Math.Sqrt () 'yi birkaç satır içi talimata derler.

Yerel C / C ++, yıllarca geriye dönük uyumluluğa sahiptir. / Fp: kesin, / fp: hızlı ve / fp: katı derleme seçenekleri en görünür olanlardır. Buna göre, sonucu ayarlamak için sqrt () uygulayan ve seçilen kayan nokta seçeneklerini kontrol eden bir CRT işlevini çağırmalıdır. Bu yavaş.


67
Bu, C ++ programcıları arasında garip bir kanaattir, C # tarafından üretilen makine kodunun yerel bir derleyici tarafından üretilen makine kodundan bir şekilde farklı olduğunu düşünüyorlar. Sadece bir tür var. Hangi gcc derleyici anahtarını kullanırsanız kullanın veya satır içi derleme yazdığınız önemli değil, yine de yalnızca bir FSQRT talimatı vardır. Her zaman daha hızlı değil çünkü onu ana dil oluşturdu, işlemci umursamıyor.
Hans Passant

17
Bu, ngen.exe ile ön jitting'in çözdüğü şeydir. Java değil, C # hakkında konuşuyoruz.
Hans Passant

21
@ user877329 - gerçekten mi? Vay.
Andras Zoltan

8
Hayır, x64 jitter SSE kullanır. Math.Sqrt (), sqrtsd makine kodu komutuna çevrilir.
Hans Passant

6
Teknik olarak diller arasında bir fark olmasa da, .net JITter, tipik bir C / C ++ derleyicisine kıyasla oldukça sınırlı optimizasyonlar yapar. En büyük sınırlamalardan biri, kodu genellikle yaklaşık 4 kat daha yavaş hale getiren SIMD desteğinin olmamasıdır. Çok fazla içkinliği açığa vurmamak da büyük bir sorun olabilir, ancak bu büyük ölçüde ne yaptığınıza bağlıdır.
CodesInChaos

57

Ben bir C ++ ve C # geliştiricisiyim. .NET çerçevesinin ilk beta sürümünden beri C # uygulamaları geliştirdim ve C ++ uygulamaları geliştirmede 20 yıldan fazla deneyime sahibim. İlk olarak, C # kodu ASLA bir C ++ uygulamasından daha hızlı olmayacak, ancak yönetilen kod, nasıl çalıştığı, operasyonlar arası katman, bellek yönetimi dahili bileşenleri, dinamik tip sistemi ve çöp toplayıcı hakkında uzun bir tartışmaya girmeyeceğim. Yine de, burada listelenen kriterlerin hepsinin YANLIŞ sonuçlar verdiğini söyleyerek devam etmeme izin verin.

Açıklayayım: Dikkate almamız gereken ilk şey, C # için JIT derleyicisidir (.NET Framework 4). Şimdi JIT, çeşitli optimizasyon algoritmaları (Visual Studio ile birlikte gelen varsayılan C ++ optimize ediciden daha agresif olma eğilimindedir) kullanarak CPU için yerel kod üretir ve .NET JIT derleyicisi tarafından kullanılan komut seti, gerçek CPU'nun daha yakın bir yansımasıdır. makinede, böylece saat döngülerini azaltmak ve CPU boru hattı önbelleğindeki isabet oranını iyileştirmek ve talimatların yeniden sıralanması ve dal tahminiyle ilgili iyileştirmeler gibi daha fazla hiper iş parçacığı optimizasyonları üretmek için makine kodunda belirli ikameler yapılabilir.

Bunun anlamı, C ++ uygulamanızı RELEASE yapısı için doğru pararmetreleri (DEBUG yapısını değil) kullanarak derlemediğiniz sürece, C ++ uygulamanız, karşılık gelen C # veya .NET tabanlı uygulamadan daha yavaş çalışabilir. C ++ uygulamanızda proje özelliklerini belirtirken, "tam optimizasyon" u etkinleştirdiğinizden ve "hızlı kodu tercih ettiğinizden" emin olun. 64 bitlik bir makineniz varsa, hedef platform olarak x64 oluşturmayı BELİRTMENİZ GEREKİR, aksi takdirde kodunuz, performansı önemli ölçüde düşürecek bir dönüşüm alt katmanı (WOW64) aracılığıyla yürütülecektir.

Derleyicide doğru optimizasyonları gerçekleştirdikten sonra, C ++ uygulaması için .72 saniye ve C # uygulaması için 1.16 saniye (her ikisi de sürüm sürümünde) elde ediyorum. C # uygulaması çok basit olduğundan ve döngüde kullanılan belleği yığın üzerinde değil yığın üzerinde tahsis ettiğinden, aslında nesnelerde, ağır hesaplamalarda ve daha büyük veri kümelerinde yer alan gerçek bir uygulamadan çok daha iyi performans göstermektedir. Dolayısıyla sağlanan rakamlar, C # ve .NET çerçevesine yönelik iyimser rakamlardır. Bu önyargı ile bile, C ++ uygulaması eşdeğer C # uygulamasına göre yarıdan biraz daha fazla sürede tamamlanır. Kullandığım Microsoft C ++ derleyicisinin doğru ardışık düzen ve hiper iş parçacığı optimizasyonlarına sahip olmadığını unutmayın (montaj talimatlarını görüntülemek için WinDBG kullanarak).

Şimdi Intel derleyicisini kullanırsak (ki bu, AMD / Intel işlemcilerde yüksek performanslı uygulamalar oluşturmak için bir endüstri sırrıdır), aynı kod C ++ yürütülebilir dosya için .54 saniyede, Microsoft Visual Studio 2010 kullanılarak .72 saniyede yürütülür. Sonuç olarak, nihai sonuçlar C ++ için .54 saniye ve C # için 1.16 saniyedir. Dolayısıyla .NET JIT derleyicisi tarafından üretilen kod, C ++ yürütülebilir dosyadan% 214 kat daha uzun sürer. .54 saniyede harcanan zamanın çoğu, döngünün kendisinden değil, sistemden zamanı almakla ilgilidir!

İstatistiklerde eksik olan şey, zamanlamalara dahil edilmeyen başlatma ve temizleme süreleridir. C # uygulamaları, başlangıçta ve sonlandırmada C ++ uygulamalarından çok daha fazla zaman harcama eğilimindedir. Bunun arkasındaki neden karmaşıktır ve .NET çalışma zamanı kodu doğrulama rutinleri ve bellek ayırmalarını ve çöpü optimize etmek için programın başında (ve sonuç olarak sonunda) çok fazla iş yapan bellek yönetimi alt sistemi ile ilgilidir. kolektör.

C ++ ve .NET IL'nin performansını ölçerken, TÜM hesaplamaların orada olduğundan emin olmak için montaj koduna bakmak önemlidir. Bulduğum şey, C # 'a bazı ek kodlar koymadan, yukarıdaki örneklerdeki kodun çoğunun aslında ikiliden kaldırıldığıdır. Bu, Intel C ++ derleyicisiyle birlikte gelen gibi daha agresif bir iyileştirici kullandığınızda C ++ için de geçerliydi. Yukarıda verdiğim sonuçlar% 100 doğrudur ve montaj düzeyinde doğrulanmıştır.

İnternetteki birçok forumda temel sorun, birçok yeni kullanıcının teknolojiyi anlamadan Microsoft pazarlama propagandasını dinlemesi ve C # 'ın C ++' dan daha hızlı olduğu konusunda yanlış iddialarda bulunması. İddia, teoride, JIT derleyicisinin CPU için kodu optimize edebilmesi nedeniyle C # 'nın C ++' dan daha hızlı olmasıdır. Bu teoriyle ilgili sorun, .NET çerçevesinde performansı yavaşlatan çok sayıda sıhhi tesisat olmasıdır; C ++ uygulamasında bulunmayan sıhhi tesisat. Ayrıca, deneyimli bir geliştirici, verilen platform için doğru derleyiciyi bilecek ve uygulamayı derlerken uygun bayrakları kullanacaktır. Linux veya açık kaynaklı platformlarda, bu bir sorun değildir çünkü kaynağınızı dağıtabilir ve uygun optimizasyonu kullanarak kodu derleyen kurulum komut dosyaları oluşturabilirsiniz. Pencerelerde veya kapalı kaynak platformunda, her biri belirli optimizasyonlara sahip birden çok yürütülebilir dosya dağıtmanız gerekecektir. Dağıtılacak Windows ikili dosyaları, msi yükleyici tarafından algılanan CPU'ya dayanır (özel eylemler kullanılarak).


23
1. Microsoft, C # ile ilgili iddialarının daha hızlı olduğu iddiasında bulunmadı; hızının yaklaşık% 90'ı, geliştirmesi daha hızlı (ve dolayısıyla ayarlama için daha fazla zaman) ve bellek ve tür güvenliği nedeniyle daha fazla hatasız. Bunların hepsi doğrudur (C ++ 'da 20 ve C #' de 10 yılım var) 2. Başlangıç ​​performansı çoğu durumda anlamsızdır. 3. LLVM gibi daha hızlı C # derleyicileri de var (bu yüzden Intel'i ortaya çıkarmak Elmalara Elmalar değildir)
ben

13
Başlangıç ​​performansı anlamsız değil. Çoğu kurumsal web tabanlı uygulamada çok önemlidir, bu nedenle Microsoft, .NET 4.0'da önceden yüklenecek (otomatik başlatma) web sayfalarını tanıttı. Uygulama havuzu arada bir geri dönüştürüldüğünde, her sayfa ilk yüklendiğinde karmaşık sayfalar için önemli bir gecikme yaşanacak ve tarayıcıda zaman aşımlarına neden olacaktır.
Richard

8
Microsoft, önceki pazarlama materyallerinde .NET'in performansının daha hızlı olduğu iddiasında bulundu. Ayrıca çöp toplayıcının performans üzerinde çok az etkisi olduğu veya hiç etkisi olmadığı hakkında çeşitli iddialarda bulundular. Bu iddialardan bazıları, önceki baskılarında çeşitli kitaplara (ASP.NET ve .NET üzerinde) dahil edildi. Microsoft, C # uygulamanızın C ++ uygulamanızdan daha hızlı olacağını özellikle söylemese de, "Just-In-Time Means Run-It-Fast" ( msdn.microsoft.com/) gibi genel yorumları ve pazarlama sloganlarını süpürebilir. en-us / library / ms973894.aspx ).
Richard

72
-1, bu rant bariz "C # kodu ASLA bir C ++ uygulamasından daha hızlı olmayacak" gibi yanlış ve yanıltıcı ifadelerle
doludur

33
-1. Rico Mariani vs Raymond Chen'in C # vs C performans savaşını okumalısınız : blogs.msdn.com/b/ricom/archive/2005/05/16/418051.aspx . Kısacası: Microsoft'taki en zeki adamlardan birinin C sürümünü basit bir C # sürümünden daha hızlı hale getirmek için çok fazla optimizasyon yapması gerekti.
Rolf Bjarne Kvinge

10

İlk tahminim bir derleyici optimizasyonu çünkü asla root kullanmıyorsunuz. Sadece atayın, ardından tekrar tekrar üzerine yazın.

Düzenleme: kahretsin, 9 saniye geç!


2
Haklısın diyorum Gerçek değişkenin üzerine yazılır ve asla bunun ötesinde kullanılmaz. Csc, büyük olasılıkla tüm döngüden vazgeçerken, c ++ derleyicisi muhtemelen onu içinde bırakacaktır. Daha doğru bir test, sonuçları biriktirmek ve sonunda bu sonucu yazdırmak olacaktır. Ayrıca, çekirdek değerini sabit kodlamamalı, bunun yerine kullanıcı tanımlı olarak bırakmalıdır. Bu, c # derleyicisine işleri dışarıda bırakmak için herhangi bir yer vermez.

7

Döngünün optimize edilip edilmediğini görmek için kodunuzu şu şekilde değiştirmeyi deneyin:

root += Math.Sqrt(i);

C kodunda benzer şekilde ans ve ardından döngünün dışında kök değerini yazdırın.


6

Belki c # derleyicisi hiçbir yerde root kullanmadığınızı fark ediyor, bu yüzden for döngüsünün tamamını atlıyor. :)

Durum böyle olmayabilir, ancak nedeni ne olursa olsun, derleyici uygulamasına bağlı olduğundan şüpheleniyorum. Optimizasyonlar ve Yayın modu ile Microsoft derleyicisiyle (cl.exe, win32 sdk'nin bir parçası olarak mevcuttur) C programını derlemeyi deneyin. Eminim diğer derleyiciye göre mükemmel bir gelişme göreceksiniz.

DÜZENLEME: Derleyicinin sadece for döngüsünü optimize edebileceğini sanmıyorum, çünkü Math.Sqrt () 'nin herhangi bir yan etkisinin olmadığını bilmesi gerekir.


2
Belki bunu biliyordur.

2
@Neil, @jeff: Katılıyorum, bunu kolaylıkla bilebilir. Uygulamaya bağlı olarak, Math.Sqrt () üzerinde statik analiz o kadar zor olmayabilir, ancak özellikle hangi optimizasyonların yapıldığından emin değilim.
John Feminella

5

Zaman farkı ne olursa olsun. bu "geçen süre" geçersiz olabilir. Bu, ancak her iki programın da aynı koşullar altında çalışacağını garanti ederseniz geçerli olacaktır.

Belki bir galibiyet denemelisin. $ / usr / bin / time my_cprog; / usr / bin / time my_csprog'a eşdeğer


1
Bu neden reddedildi? Kesintilerin ve bağlam anahtarlarının performansı etkilemediğini varsayan var mı? TLB özledikleri, sayfa değiş tokuşu vb. Hakkında varsayımlarda bulunan var mı?
Tom

5

C ve C # dillerinde (kodunuza göre) iki karşılaştırılabilir test daha bir araya getirdim. Bu ikisi, indeksleme için modül işlecini kullanarak daha küçük bir dizi yazar (bu biraz ek yük getirir, ancak hey, [kaba bir düzeyde] performansı karşılaştırmaya çalışıyoruz).

C kodu:

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <math.h>

void main()
{
    int count = (int)1e8;
    int subcount = 1000;
    double* roots = (double*)malloc(sizeof(double) * subcount);
    clock_t start = clock();
    for (int i = 0 ; i < count; i++)
    {
        roots[i % subcount] = sqrt((double)i);
    }
    clock_t end = clock();
    double length = ((double)end - start) / CLOCKS_PER_SEC;
    printf("Time elapsed: %f\n", length);
}

C # dilinde:

using System;

namespace CsPerfTest
{
    class Program
    {
        static void Main(string[] args)
        {
            int count = (int)1e8;
            int subcount = 1000;
            double[] roots = new double[subcount];
            DateTime startTime = DateTime.Now;
            for (int i = 0; i < count; i++)
            {
                roots[i % subcount] = Math.Sqrt(i);
            }
            TimeSpan runTime = DateTime.Now - startTime;
            Console.WriteLine("Time elapsed: " + Convert.ToString(runTime.TotalMilliseconds / 1000));
        }
    }
}

Dizi önemli ölçüde daha küçük olmasına rağmen (aşırı bellek kullanmak istemedi) bu testler bir diziye veri yazar (bu nedenle .NET çalışma zamanının sqrt işlemcisini toplamasına izin verilmemelidir). Bunları sürüm yapılandırmasında derledim ve bunları bir konsol penceresinden çalıştırdım (VS ile başlamak yerine).

Bilgisayarımda C # programı 6.2 ile 6.9 saniye arasında değişirken, C versiyonu 6.9 ile 7.1 arasında değişiyor.


5

Karekök yordamına adım atmak da dahil olmak üzere, derleme düzeyinde kodu tek adımlıyorsanız, muhtemelen sorunuzun cevabını alacaksınız.

Eğitimli tahmin yapmaya gerek yok.


Bunu nasıl yapacağımı öğrenmek istiyorum
Josh Stodola

IDE'nize veya hata ayıklayıcınıza bağlıdır. Pgm başlangıcında kırın. Demontaj penceresini görüntüleyin ve tek adımlı uygulamaya başlayın. GDB kullanılıyorsa, bir seferde bir talimatı adımlamak için komutlar vardır.
Mike Dunlavey

Şimdi bu iyi bir ipucu, bu, aşağıda gerçekte neler olup bittiğini daha iyi anlamanıza yardımcı olur. Bu, satır içi ve kuyruk aramaları gibi JIT optimizasyonlarını da gösteriyor mu?
gjvdkamp

Bilginize: Benim için bu, fadd ve fsqrt kullanarak VC ++ 'ı gösterirken, C #, anladığım kadarıyla SSE2 komutları olan ve desteklendiğinde önemli ölçüde daha hızlı olan cvtsi2sd ve sqrtsd'yi kullandı.
danio

2

Burada bir sorun olabilecek diğer faktör, C derleyicisinin hedeflediğiniz işlemci ailesi için genel yerel koda derlemesidir, oysa C # kodunu derlediğinizde oluşturulan MSIL daha sonra JIT, herhangi bir işlemciyle tamamladığınız tam işlemciyi hedeflemek için derlenir. mümkün olabilecek optimizasyonlar. Dolayısıyla, C # 'dan üretilen yerel kod C'den önemli ölçüde daha hızlı olabilir.


Teorik olarak, evet. Pratikte, bu neredeyse hiçbir zaman ölçülebilir bir fark yaratmaz. Şanslıysanız, belki yüzde veya iki.
jalf

veya - 'genel' işlemci için izin verilenler listesinde bulunmayan uzantıları kullanan belirli bir kod türünüz varsa. SSE tatları gibi şeyler. Hangi farklılıkları elde ettiğinizi görmek için işlemci hedefi daha yükseğe ayarlanmış olarak deneyin.
gbjbaanb

1

Bana öyle geliyor ki, bunun dillerin kendisiyle bir ilgisi yok, bunun yerine karekök işlevinin farklı uygulamaları ile ilgili.


Farklı sqrt uygulamalarının bu kadar eşitsizliğe neden olacağından şüpheliyim.
Alex Fort

Özellikle C # 'da bile matematik fonksiyonlarının çoğu hala performans açısından kritik kabul edildiğinden ve bu şekilde uygulandığından.
Matthew Olenik

fsqrt bir IA-32 işlemci talimatıdır, bu nedenle dil uygulaması bugünlerde konu dışıdır.
Değil Emin

Bir hata ayıklayıcı ile MSVC'nin sqrt işlevine adım atın. Sadece fsqrt komutunu yürütmekten çok daha fazlasını yapıyor.
bk1e

1

Aslında çocuklar, döngü optimize edilmiyor. John'un kodunu derledim ve ortaya çıkan .exe dosyasını inceledim. Döngünün bağırsakları aşağıdaki gibidir:

 IL_0005:  stloc.0
 IL_0006:  ldc.i4.0
 IL_0007:  stloc.1
 IL_0008:  br.s       IL_0016
 IL_000a:  ldloc.1
 IL_000b:  conv.r8
 IL_000c:  call       float64 [mscorlib]System.Math::Sqrt(float64)
 IL_0011:  pop
 IL_0012:  ldloc.1
 IL_0013:  ldc.i4.1
 IL_0014:  add
 IL_0015:  stloc.1
 IL_0016:  ldloc.1
 IL_0017:  ldc.i4     0x5f5e100
 IL_001c:  ble.s      IL_000a

Çalışma zamanı, döngünün hiçbir şey yapmadığını ve onu atladığını fark edecek kadar akıllı olmadığı sürece?

Düzen: C # değiştirilerek şu şekilde değiştirilir:

 static void Main(string[] args)
 {
      DateTime startTime = DateTime.Now;
      double root = 0.0;
      for (int i = 0; i <= 100000000; i++)
      {
           root += Math.Sqrt(i);
      }
      System.Console.WriteLine(root);
      TimeSpan runTime = DateTime.Now - startTime;
      Console.WriteLine("Time elapsed: " +
          Convert.ToString(runTime.TotalMilliseconds / 1000));
 }

Geçen zamanın sonuçları (benim makinemde) 0,047'den 2,17'ye çıkıyor. Ancak bu, 100 milyon ekleme operatörü eklemenin sadece ek yükü mü?


3
IL'ye bakmak size optimizasyonlar hakkında pek bir şey söylemez çünkü C # derleyicisi sabit katlama ve ölü kodu kaldırma gibi bazı şeyler yapsa da, IL daha sonra görevi devralır ve kalanını yükleme zamanında yapar.
Daniel Earwicker

Durumun bu olabileceğini düşündüm. Çalışması için zorlasa bile, yine de C sürümünden 9 saniye daha hızlı. (Bunu hiç beklemiyordum)
Dana
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.