Kodumu yazarken derlenmiş makine kodunu düşünmeli miyim?


20

Örneğin aşağıdaki kodu aldım:

auto z = [](int x) -> int {
    if (x > 0) {
        switch (x) {
            case 2: return 5;
            case 3: return 6;
            default: return 1;
            }
        }
    return 0;
    };

Ve sonra bunu birkaç kez arıyorum. Asm kodunda lambda ile dış aramalar görüyorum .... bir şey ... Okumak kolaylaşmıyor ve aynı zamanda performansa neden olabileceğini düşünüyorum. Belki meta-programlamada kazanıyorum ama asm hata ayıklama ve performansta kaybediyor muyum? Performans ve hata ayıklama basitliğinde emin olmak için modern dil özelliklerinden, makrolardan ve diğer meta programlama özelliklerinden kaçınmalı mıyım?


1
Derleyicinin sürümüne ve birlikte verilen standart kütüphanesine bağlı olarak, lambda gerçekten verimsiz bir şekilde uygulanabilir. Stackoverflow ile ilgili bu soruya bakın . Ancak, geliştirme sorumluluğu derleyici satıcısına aittir.
rwong

15
Kritik performans yolunda değilseniz montaj kodunda hata ayıklamanız gerekmez. Ayrıca, "temiz kod"! = "İyi performanslar".
BЈовић

Girintinizi düzeltin lütfen. Bunu yapmaya çalıştım, ama sadece boşluk düzenleyemezsiniz.
Christoffer Hammarström

3
@Heather: Daha önce hiç görmediğim ve okumakta zorlandığım Ratliff stilini kullanıyor görünüyorsun . Kesinlikle daha az bilinenlerden biri. Benim izlenimim düzgün girintili olmamanızdı. Boşver eğer okunabilir bulursan ben katılmıyorum.
Christoffer Hammarström

1
ifÖrnek kodda tamamen gereksiz ve derleyici muhtemelen o yakalayacak ederken kötü bir dal tahminini cezbedecek hiçbir neden yoktur.
dmckee

Yanıtlar:


59

Kodumu yazarken derlenmiş makine kodunu düşünmeli miyim?

Hayır , kodunuzu ilk kez yazdığınızda ve gerçek, ölçülebilir performans sorunlarından muzdarip olmadığınızda değil. Çoğu görev için bu standart durumdur. Optimizasyon hakkında çok erken düşünmeye "erken optimizasyon" denir ve D. Knuth'un bunu "tüm kötülüğün kökü" olarak adlandırmasının iyi nedenleri vardır .

Evet , gerçek, kanıtlanabilir bir performans darboğazını ölçtüğünüzde ve belirli lambda yapısını temel neden olarak tanımladığınızda. Bu durumda, Joel Spolsky'nin "sızdıran soyutlamalar yasasını" hatırlamak ve asm düzeyinde neler olabileceğini düşünmek iyi bir fikir olabilir. Ancak dikkat edin, lambda yapısını "modern olmayan" bir dil yapısıyla değiştirdiğinizde (en azından iyi bir C ++ derleyicisi kullanırken) performans artışının ne kadar küçük olacağına şaşırabilirsiniz.


2
+1 Her zamanki gibi, özlü, doğru ve takip edilmesi kolay Doc, burada olmanızdan memnunum.
Jimmy Hoffa

Anlaşıldı, çok net bir cevap.
cnd

8

Lambda ve functor sınıfı arasındaki seçim bir ödünleşmedir.

Lambda'dan elde edilen kazanç, kazan plakası miktarını en aza indirgeyerek ve kavramsal olarak ilgili kodun, onu kullanacak fonksiyonun içinde (hemen veya daha sonra) satır içinde yazılmasına izin vererek çoğunlukla sözdizimseldir.

Performans açısından, bu bir C ++ yapısı veya tek bir "yöntem" içeren sınıf olan bir functor sınıfından daha kötü değildir . Aslında, derleyiciler lambda'yı sahnenin arkasında derleyici tarafından üretilen bir functor sınıfından farklı şekilde ele almazlar.

// define the functor method somewhere
struct some_computer_generated_gibberish_0123456789
{
    int operator() (int x) const
    {
        if (x == 2) return 5;
        if (x == 3) return 6;
        return 0;
    }
};

// make a call
some_computer_generated_gibberish_0123456789 an_instance_of_0123456789;
int outputValue = an_instance_of_0123456789(inputValue);

Kod örneğinizde, performans açısından bir işlev çağrısından farklı değildir, çünkü bu functor sınıfının hiçbir durumu yoktur (çünkü boş bir yakalama cümlesi vardır), bu nedenle tahsis, kurucu veya yıkım gerektirmez.

int some_computer_generated_gibberish_0123456789_method_more_gibberish(int x)
{
    if (...) return ...;
    return ...;
}

Önemsiz bir C ++ kodunu bir sökücü kullanarak hata ayıklamak her zaman zor bir iş olmuştur. Bu lambda kullanarak veya kullanmadan doğrudur. Bunun nedeni, C ++ derleyicisinin yeniden sıralama, serpiştirme ve ölü kod ortadan kaldırmasıyla sonuçlanan karmaşık kod optimizasyonudur.

İsim yönetme yönü biraz tatsızdır ve lambda için hata ayıklayıcı desteği hala başlangıç ​​aşamasındadır . Yalnızca hata ayıklayıcı desteğinin zaman içinde iyileşeceği umulmaktadır.

Şu anda, lambda kodunda hata ayıklamanın en iyi yolu, kaynak kod düzeyinde kesme noktalarını ayarlamayı destekleyen bir hata ayıklayıcı kullanmaktır, yani kaynak dosya adını ve satır numarasını belirterek.


3

@DocBrown tarafından verilen cevaba eklemek için, bu günlerde CPU'ların ucuz ama işçinin pahalı olduğunu unutmayın.

Bir programın toplam maliyetinde, donanım, tipik bir projenin en pahalı parçası olan (geliştirilmesinden bile daha fazla) bakım maliyetine kıyasla genellikle önemsizdir.

Bu nedenle, performans kritik olduğunda (ve hatta bakımın göz önünde bulundurulması gerektiğinde) kodunuzun bakımı her şeyin üstünde optimize etmesi gerekir.


Sadece kısmen doğrudur. Kodunuz O (n ^ 2) (karesel) çalıştırıyorsa ve daha iyi O (log (n)) (logaritmik) diyelim. Orijinal poster tarafından belirtilen durumda, bu pek olası değildir.
gnash117

@ gnash117 - evet, kod birçok kez çalıştırılacaksa haklısınız; bunu işaret ettiğiniz için teşekkür ederim. Bu gibi durumlarda, kodun açık bir şekilde belgelenmesi, performansın iyileştirilmesine izin verirken kodun korunmasını sağlayacaktır.
Paddy Landau

"emek pahalıdır" - Doğru. Müşterinizin zamanı çok önemlidir ve genellikle pahalıdır.
Cerad
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.