Thread overview
Andrei Alexandrescu'nun "Three Optimization Tips for C++" konuşması
Dec 23, 2012
Salih Dinçer
Dec 23, 2012
Salih Dinçer
Dec 28, 2012
Salih Dinçer
December 22, 2012

Bu konuşma D ve başka diller için de aynı derecede önemli çünkü mikroişlemci ve bellek işlemleriyle ilgili. New York'ta Facebook'ta konuşmuş. Reddit konusu şurada:

http://www.reddit.com/r/programming/comments/155ivw/three_optimization_tips_for_c_video/

Konuşmayı görüntülü olarak artık izleyemiyorum çünkü vimeo özel olduğunu söylüyor ama tam olarak şu:

http://vimeo.com/55639112

Neyse ki saydamlar mevcut:

http://www.slideshare.net/andreialexandrescu1/three-optimization-tips-for-c-15708507

Üç temel ilke şunlar:

  • Ölçmeden bilemezsiniz

  • Güçlü işlemleri azaltın

  • Dizi yazma işlemlerini azaltın

Verilen bir sayının on tabanındaki gösteriminin kaç haneden oluştuğunu döndüren digits10() işlevi üzerinde duruyor. Onu hızlandırdıktan sonra ondan yararlanan ve 64 bitlik sayıyı dizgiye dönüştüren u64ToAsciiClassic() ve u64ToAsciiTable() işlevlerinde kullanıyor.

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

December 23, 2012

Teşekkürler Ali hocam, dinlemeye başladım...:)

Yansıları da vermiş olman sayesinde ortadaki kameranın alamadığı görüntüyü takip edebiliyoruz. Neyse ki Vimeo gıcıklık yapmadı tıklar tıklamaz çalıştı.

Sevgiler, saygılar...

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

December 23, 2012

Harikaydı gerçekten, bu adamlar çok akıllı...:)

Şu koda bakar mısınız!

 enum {
   P01 = 10, P02 = 100, P03 = 1_000, P04 = 10_000,
   P05 = 100_000, P06 = 1_000_000, P07 = 10_000_000,
   P08 = 100_000_000, P09 = 1_000_000_000,
   P10 = 10_000_000_000, P11 = 100_000_000_000,
   P12 = 1_000_000_000_000,
 }

 size_t digits10(size_t v) {
   if(v < P01) return 1;
   if(v < P02) return 2;
   if(v < P03) return 3;
   if(v < P12) {
     if(v < P08) {
       if(v < P05) {
         if(v < P04) return 4;
         return 5 + (v < P05);
       }
       return 7 + (v >= P07);
     }
     if(v < P10) {
       return 9 + (v >= P09);
     }
     return 11 + (v >= P11);
   }
   return 12 + digits10(v / P12);
 }

void main() {
 assert(1234567.digits10 == 7);
}

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

December 23, 2012

Haklısın. İşin temelinde ölçüm var: Programın zamanının en çok hangi işlem(ler)de geçtiğini belirledikten sonra oraya odaklanıyorlar.

Benim ilgimi çeken bir tanesi de şuydu: 'dizi[i++]' işlemi 'dizi[++i]' işleminden daha hızlı olabiliyormuş. Ama söylemek istediği, öyle bir arada yazılması değil. Asıl söylediği şu:

// Daha hızlı olan işlem:
dizi[i];
++i;

// Daha yavaş olan işlem:
++i;
dizi[i];

Tabii, iki kodun aynı anlamda olmadığını biliyoruz. Eğer algoritmayı birinci yöntemdeki gibi yazarsak, mikroişlemci 'dizi[ i ]' ile bellek erişiminin sonucunu beklerken bir yandan da '++i' işlemini gerçekleştirebiliyormuş. İkinci yöntemde ise böyle bir şans yok: Önce i'nin arttırılması ve belleğe onun değeriyle erişilmesi gerektiğinden mikroişlemci ikisin aynı anda işletemiyor.

Bu konular gerçekten çok ilginçleşmiş. :)

Aklıma gelen bir tane daha: Mikroişlemci belleğe belirli bir yönde art arda erişildiğini sezerek belleği baştan okuyabiliyormuş (prefetch). Yani, resmen bir dizinin elemanlarına eriştiğimizi farkedip ona göre davranıyormuş. Bunu da hiç duymamıştım; bu konuşmada öğrendim. :)

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

December 28, 2012

Dizilerde index değerinin arttırlması ve dizi elemanına erişim hakkındaki yavaşlığı, üstelik koşut yapabilme yeteneğini bilmiyordum. Elbette bunlara itiarazım yok ve doğru olmalılar. Ancak şöyle bir şey var, kod ile açılayayım:

struct Stack {
   int index;
   int[] stack;

   void push(int data) @property {
       stack ~= data;
       index++;
   }

   int pop() @property  {
       --index;
       // önce eksiltmeliyiz çünkü dizin ilk elemanı 0'dır (boş değildir)
       auto value = stack[index];
       stack.length = index;
       return value;
   }

   ref int top() @property  {
       return stack[index - 1];
   }
}

Yukarıdaki çok basit bir yığıt yapısı. Belki açıklamaya bile ihtiyaç bırakmıyor. Ancak az önce yerleştirdiğim küçük açıklama öneme binaen yazıldı. Çünkü birbirine bağlı iki satırdan bahsediyoruz. Önce ve sonra kavramları önemli.

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

December 28, 2012

Mikroişlemci programın tanımını değiştirecek hiçbir şey yapmıyor; yapmamalı da zaten. Yalnızca elindeki makine koduna bakıyor. Şöyle iki işlem olsun:

++i;
++j;

Eğer i ve j iki yazmaçta iseler mikroişlemci ikincisinin değerini arttırmak için birincisinin bitmesini beklemiyor çünkü iki yazmacın değerlerinin birbirlerine bağlı değil.

Bu konuşmada dikkat çekilen konu şu: Eğer tasarım önce '--index' sonra 'stack[index]' biçimindeyse, mikroişlemci bu konuda yardım getiremez. Eğer tasarım 'önce stack[index]' sonra '--index' biçimindeyse mikroişlemci bu kodu daha hızlı işletebilir. Bunun hangi veri yapılarına uygun olduğuna da hiç girmedi. Eğer algoritmayı her iki türlü de kurabiliyorsak bunu akılda tutmakta yarar var.

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]