Thread overview
Dallanma Alternatifi
Jul 14, 2023
Salih Dincer
Jul 14, 2023
Salih Dincer
Jul 14, 2023
Ferhat Kurtulmuş
Jul 14, 2023
Ferhat Kurtulmuş
July 14, 2023

Merhaba,

Gün geçmiyor ki insan yeni bir şey öğrenmesin. Şimdi nakledeceklerim basit şeyler ama sizi farklı düşünmeye sevk ediyor. Elbette günümüz işlemcileri için gereksiz olabilir; her şey eğitim için...

Önce 8 bölümlük kaynak vidyo:

https://youtu.be/bVJ-mWWL7cE

Ve etkileyici ilk örneğimiz:

void toUpperASCII2(char[] str)
{
  foreach(ref c; str)
  {
    c -= cast(char)(32 * (c >= 'a' && c <= 'z'));
  }
}

Bu std.ascii'de tek karakteri çeviren toUpper'ın bir benzeri. Ama orada hem isLower kullanılmış hem üçlü işleç ile klasik if/else mantığı var. Yoksa yine ASCII karakterden 32 çıkarılıyor...

Lütfen bir düşünün; verdiğim işlevi 1 milyon karakterli bir metni büyük harfe çevirmek için kullansanız, işlemciyi deli meşgul eder. Hatta bu sade görünen örneği, assembly kodunda daha iyi opimize edilen bir benzeri tavsiye ediliyor:

void toUpperASCII1(char[] str)
{
  foreach(ref c; str)
  {
    c = cast(char)((  c * !(c >= 'a' && c <= 'z')) +
                (c - 32) * (c >= 'a' && c <= 'z'));
  }
}

Aradaki farka bakın ve sizin için 1 numara hangisi deneyip karar verin lütfen. Zaten kaynak vidyoda veya disassembly yaparsanız gerçek kodlarda bu farkı göreceksiniz...

Şimdi yine aynı mantıkla tasarlanan 2 minMax işlevi örneği vereceğim. Bu kaynaktaki ilk örnek ve eğer mantığı anlarsanız sadece matematiksel işlemler ile optimizasyon garanti.

int maxMin(int a, int b)
{
  if(a < b)
    return a;
  else
    return b;
}

int minMax(int a, int b)
{
  return a * (a < b) + b * (b <= a);
}


unittest
{
  int i = 3;
  int j = 5;
  assert(i.minMax(j) == i.maxMin(j));

  import std.algorithm.mutation;
  i.swap(j);
  assert(i.minMax(j) == i.maxMin(j));
}

İlk işlev bizim her zaman yaptığımız klasik mantık. Tabi kodunuza uygunsa bunu ikinci işlevde olduğu gibi yapabilirsiniz. Farkettiyseniz dönen sonuçta da bir Boolean matematiği var. Ama dikkat, kodu disaasembling yaptığınızda dallanma komutları işleri karıştırıyor! Ne kadar -O2 gibi parametrelerle derlerseniz derleyin, sizin koda doğrudan yaptığınız optimizasyon kadar etkili olmayacaktır. Çünkü bütün bunlar domimant optimizasyonlar.

Başarılar...

July 14, 2023

Aklıma gelmişken, bir de D'ye has bir özellikten bahsetmek bu başlığa yakıiacaktır. Kodumuz şöyle:

init:
  int i, j;

loop:
  for(i = 3; i > 0; --i)
  {
    for (j = 5; j > 0; --j)
    {
      if(i == j) break loop;
      i.writeln(" : ", j);
    }
  }

Eğer break loop yerine sıradan döngüyü kırarsanız, sadece içtekinden çıkacaktır. Bu, size, belki de hiç istemediğiniz 9 sonucu gösterecektir. Ama yukardaki kod sadece 2 sonucu ekrana yazar.

July 14, 2023

On Friday, 14 July 2023 at 00:25:52 UTC, Salih Dincer wrote:

>

Merhaba,

Gün geçmiyor ki insan yeni bir şey öğrenmesin. Şimdi nakledeceklerim basit şeyler ama sizi farklı düşünmeye sevk ediyor. Elbette günümüz işlemcileri için gereksiz olabilir; her şey eğitim için...

[...]

Salih merhaba, verdiğin videoda arkadaşın dediğine göre c++ derleyicisi if ile yazdığımız bazı kodları assemblye çevirirken dallanmasız versiyonu ile yazıyor diyor. Acaba d derleyicisi de aynı akıllıca çevirmeyi yapıyor mu?

July 14, 2023

On Friday, 14 July 2023 at 00:25:52 UTC, Salih Dincer wrote:

>

Merhaba,

Gün geçmiyor ki insan yeni bir şey öğrenmesin. Şimdi nakledeceklerim basit şeyler ama sizi farklı düşünmeye sevk ediyor. Elbette günümüz işlemcileri için gereksiz olabilir; her şey eğitim için...

Önce 8 bölümlük kaynak vidyo:

https://youtu.be/bVJ-mWWL7cE

Ve etkileyici ilk örneğimiz:

void toUpperASCII2(char[] str)
{
  foreach(ref c; str)
  {
    c -= cast(char)(32 * (c >= 'a' && c <= 'z'));
  }
}

Bu std.ascii'de tek karakteri çeviren toUpper'ın bir benzeri. Ama orada hem isLower kullanılmış hem üçlü işleç ile klasik if/else mantığı var. Yoksa yine ASCII karakterden 32 çıkarılıyor...

Lütfen bir düşünün; verdiğim işlevi 1 milyon karakterli bir metni büyük harfe çevirmek için kullansanız, işlemciyi deli meşgul eder. Hatta bu sade görünen örneği, assembly kodunda daha iyi opimize edilen bir benzeri tavsiye ediliyor:

void toUpperASCII1(char[] str)
{
  foreach(ref c; str)
  {
    c = cast(char)((  c * !(c >= 'a' && c <= 'z')) +
                (c - 32) * (c >= 'a' && c <= 'z'));
  }
}

Aradaki farka bakın ve sizin için 1 numara hangisi deneyip karar verin lütfen. Zaten kaynak vidyoda veya disassembly yaparsanız gerçek kodlarda bu farkı göreceksiniz...

Şimdi yine aynı mantıkla tasarlanan 2 minMax işlevi örneği vereceğim. Bu kaynaktaki ilk örnek ve eğer mantığı anlarsanız sadece matematiksel işlemler ile optimizasyon garanti.

int maxMin(int a, int b)
{
  if(a < b)
    return a;
  else
    return b;
}

int minMax(int a, int b)
{
  return a * (a < b) + b * (b <= a);
}


unittest
{
  int i = 3;
  int j = 5;
  assert(i.minMax(j) == i.maxMin(j));

  import std.algorithm.mutation;
  i.swap(j);
  assert(i.minMax(j) == i.maxMin(j));
}

İlk işlev bizim her zaman yaptığımız klasik mantık. Tabi kodunuza uygunsa bunu ikinci işlevde olduğu gibi yapabilirsiniz. Farkettiyseniz dönen sonuçta da bir Boolean matematiği var. Ama dikkat, kodu disaasembling yaptığınızda dallanma komutları işleri karıştırıyor! Ne kadar -O2 gibi parametrelerle derlerseniz derleyin, sizin koda doğrudan yaptığınız optimizasyon kadar etkili olmayacaktır. Çünkü bütün bunlar domimant optimizasyonlar.

Başarılar...

Görünen o ki senin verdiğin örnek için farklı ASM üretiliyor. Dallanmalı olanda (maxMin) L1B etiketine zıplama var. minMax (dallanmasız) olanda kod öylece akıp gidiyor zıplama olmadan.

maxMin:
		push	RBP
		mov	RBP,RSP
		sub	RSP,010h
		mov	-010h[RBP],EDI
		mov	-8[RBP],ESI
		mov	EAX,-010h[RBP]
		cmp	EAX,-8[RBP]
		jge	L1B
		mov	EAX,-010h[RBP]
		leave
		ret
L1B:		mov	EAX,-8[RBP]
		leave
		ret
.text.maxMin	ends
.text.minMax	segment
	assume	CS:.text.minMax
minMax:
		push	RBP
		mov	RBP,RSP
		sub	RSP,010h
		mov	-010h[RBP],EDI
		mov	-8[RBP],ESI
		mov	EAX,-8[RBP]
		cmp	-010h[RBP],EAX
		setl	AL
		and	EAX,1
		imul	EAX,-010h[RBP]
		mov	ECX,-8[RBP]
		cmp	ECX,-010h[RBP]
		setle	DL
		and	EDX,1
		imul	EDX,ECX
		add	EAX,EDX
		leave
		ret
		add	[RAX],AL
.text.minMax	ends