Neden ASM ile yazılan kodlar güncel mimarilerde daha yavaş çalışır...

Başlatan gerbay, 07 Eylül 2016, 00:33:32

gerbay

hazır şurada kodu yazmışken bu konuya da gireyim dedim;

https://www.picproje.org/index.php/topic,65521.msg508914/topicseen.html#msg508914

öncelikle üzerinde düşünmek için Cortex-M7 pipeline ı şuraya bi koyalım, elimizin altında bulunsun, derdimizi anlatmak için gerekecek;


dual shifter, dual alu kısmına dikkat edin. load/store pipe M7 de bir tane ama daha fazla load-store pipe ı olanlar da var.

örnek kodumuz da şu;
int x;
volatile int y;

void increment()
{
	x++;
	y++;
}


bu kodu optimize şekilde (pipeline opt hariç) derlediğinizde şu kod alırsınız;
.text.increment:00000004                         ; void increment()
.text.increment:00000004                                     EXPORT increment
.text.increment:00000004                         increment
.text.increment:00000004 04 4A                               LDR     R2, =x              ; Load from Memory
.text.increment:00000006 13 68                               LDR     R3, [R2]            ; Load from Memory
.text.increment:00000008 01 33                               ADDS    R3, #1              ; Rd = Op1 + Op2
.text.increment:0000000A 13 60                               STR     R3, [R2]            ; Store to Memory

.text.increment:0000000C 03 4A                               LDR     R2, =y              ; Load from Memory
.text.increment:0000000E 13 68                               LDR     R3, [R2]            ; Load from Memory
.text.increment:00000010 01 33                               ADDS    R3, #1              ; Rd = Op1 + Op2
.text.increment:00000012 13 60                               STR     R3, [R2]            ; Store to Memory

.text.increment:00000014 70 47                               BX      LR                  ; Branch to/from Thumb mode
.text.increment:00000014                         ; End of function increment
.text.increment:00000014
.text.increment:00000014                         ; ---------------------------------------------------------------------------
.text.increment:00000016 00 BF                               ALIGN 4
.text.increment:00000018 20 00 00 00             off_18      DCD x                       ; DATA XREF: incrementr
.text.increment:0000001C 24 00 00 00             off_1C      DCD y                       ; DATA XREF: increment+8r
.text.increment:0000001C                         ; .text.increment ends


normalde insan da yazsa benzer mantık ile yazar. x i ve y yi memory den register a alıp, artırıp, memory de ki yerine geri yazma olayı net olarak görülüyor.

ilk bakışta çok mantıklı şekilde üretilmiş "konu bütünlüğü" olan bir kod. pipeline açısından dikkat ederseniz bir sonraki operasyon hep bir önceki operasyon ile ilgili işleme bağımlı.

böyle üretilmiş (ya da el ile yazılmış) bir kod da pipeline da bulunan bloklar paralel şekilde kullanılamaz. şimdi bu basit kodun pipeline kullanımı için optimize edilmiş compiler çıktısına da bakalım;
.text.increment:00000004                         ; void increment()
.text.increment:00000004                                     EXPORT increment
.text.increment:00000004                         increment
.text.increment:00000004 04 48                               LDR     R0, =x              ; Load from Memory
.text.increment:00000006 05 49                               LDR     R1, =y              ; Load from Memory
.text.increment:00000008 02 68                               LDR     R2, [R0]            ; Load from Memory
.text.increment:0000000A 0B 68                               LDR     R3, [R1]            ; Load from Memory
.text.increment:0000000C 01 32                               ADDS    R2, #1              ; Rd = Op1 + Op2
.text.increment:0000000E 01 33                               ADDS    R3, #1              ; Rd = Op1 + Op2
.text.increment:00000010 02 60                               STR     R2, [R0]            ; Store to Memory
.text.increment:00000012 0B 60                               STR     R3, [R1]            ; Store to Memory
.text.increment:00000014 70 47                               BX      LR                  ; Branch to/from Thumb mode
.text.increment:00000014                         ; End of function increment
.text.increment:00000014
.text.increment:00000014                         ; ---------------------------------------------------------------------------
.text.increment:00000016 00 BF                               ALIGN 4
.text.increment:00000018 20 00 00 00             off_18      DCD x                       ; DATA XREF: incrementr
.text.increment:0000001C 24 00 00 00             off_1C      DCD y                       ; DATA XREF: increment+2r
.text.increment:0000001C                         ; .text.increment ends


bu 2 fonksiyon da assembly kodu olarak aynı şekilde çalışır. 2. kodda gördüğünüz gibi x ve y üzerinde yapılan işlemler ayrılmamış, bir birinin içinde paralel şekilde yapılıyor. Dikkat ederseniz ardışık işlemler birbirinin sonucunu beklemeyecek şekilde ayarlanmış.

Böyle bir kodda load/store pipeline ı birden fazla olan işlemcilerde aynı clock cycle da üst 2 komut birden çalıştırılabilir. M7 açısında load/store tek pipe olduğu için tek tek çalıştırılır. sonraki 3. ve 4. satırlar için de aynı şey geçerli.

sonraki "adds" satırının en başına geldiğimizi düşünelim; register lar yüklenmiş durumda ve 2 tane bir biri ile ilgisi olmayan artırma işlemi var. bizim işlemci de dual ALU. işte burada bu 2 işlem aynı anda gerçekleştirilir. sonrakiler ise tek load/store pipe olduğundan dolayı yukardaki ile aynı şekilde yapılır.

bizim kod örneğimiz çok basitti ve 2 tane artırma vardı, float pipe a gidecek birşey yoktu, MAC pipe a gidecek birşey yoktu vs.

Benim yazdığım bu örnekteki gibi basit değil de normal ya da karmaşık bir kod yazdığınızı düşünün; işte bu durumda sizin hiç ASM ile uğraşamayacağınız şekilde kombinasyonları akıllı bir derleyici ayarlar ve pipeline ı sizin ASM ile yapamayacağınız kadar optimize şekilde kullanır.

iş bu sebepten dolayı kaliteli bir compiler superscalar mimari kullanan işlemcilerde sizin ASM ile yazamayacağınız şekilde hızlı çalışacak kodlar üretir. hele bir de dual/load store pipeline içeren bir işlemci için yukardaki kodun çalışmasını düşünün. bir de ilk üretilen kodun çalışmasını düşünün..

haa zevk için yazıyorsanız ya da C derleyicisinin yapamayacağı şeyleri ASM ile yapıyorsanız diyeceğim bir şey yok ama en azından artık kimse ASM ile yazılmış kodların daha hızlı çalışacağını iddia edemez. tabiki bu dediğim superscalar mimari kullanan işlemciler için geçerli ama artık işlemci dünyası tamamen superscalar mimariye kayıyor..

mert3162

Hocam basit bir örnek vermek isterim müsaadenizle asm ile bir şeyi lcd de göstermek için yazdığımız kodların uzunluğunu düşünüyorum okuldayken birde şimdi c ile yazdığımız printf komutunu karşılaştıracak olursak zaten zamanla programlama dillerinin gelişimiyle programların kısaldığı bu sebeple programın çevrim süresine etkileri ortaya çıkıyor. Assembler da basit bir gecikme bile sağlamak için bile sayaçlar oluşturup onları döngüye sokup bişeyleri zorlamak aşırı saçma geliyordu.Ve hatta ilk öğrenirken basic bilmiyorduk basitçe pause 500 yazıp programa gecikme koyma fikri varken neden bize assembler öğretiyorlar diye baya kızmıştım.(ki bana bunu öğreten yanında staj yaptığım @nonstradam a saygılar:))

Şu saatten sonra yeni öğreneceklere şöyle ifade etmek isterim ki size bu işin temeli assembler bunu öğrenmeden hiç birşey yapamazsınız diyenlere kulaklarınızı tıkayın ve gereksiz bilgilerle kafanızı meşgul etmeyin bunu öğreneceğiniz kadar uğraşacağınız sürede kendinize zor algoritma soruları oluşturup bunları çözün(programlayın) daha iyi.Bizim okulun bilgisayar programcılığı öğrencilerine kahve nasıl pişirilir programı yazdırıyorlardı algoritma derslerinde hala bu olay devam ediyor mu bilmiyorum ama bu tarz soruları çözmenizin daha iyi olacağı kanaatindeyim.
|^^^^^^^^^^^^\ ||\
|__PICPROJE.ORG __
||'""|""\___
| _____________ l | |__|__|___| )
(@!)!(@)"""""**|(@) (@)****|(@)---------

 Üstadlarım nonstradam & Logan

z

@gerbay hocam

ASM yazım gerçekten gönül işidir.

Modern dokuma tezgahları varken hâla birileri elde halı dokur, elde araba kaportası yapar ve çok büyük paralara alıcı bulur.

CM7'deki ilave kuralları öğrenmek at ile deve değil. Verdiğin örnek çok hızlı çalışması gereken bir fonksiyon için yazılmışsa
asm yazan adam sadece kullanacağı komutlara odaklanmaz hız artışı için yapılabilecek herşeye kafa yorar.
Mesela bu örnekte ben verilerin ram üzerine serpiştirildiği adreslere de odaklanır ve bu kodu aşağıdaki şekilde yazarak biraz daha hızlanmasını sağladığım gibi bir register daha az kullanarak bir başka örnek için bunu bir başka amaçla kullanma yolunun önünü açardım.

int x;
volatile int y;

void increment()
{
	x++;
	y++;
}


C Kodlarımız maden yukarıdaki kodlar, öncelikle X ve Y yi  ramda peş peşe tanımlardım (zaten öyle tanımlanmış). Olaya biraz daha geniş çerçeveden bakıp;

Kodlamamı aşağıdaki gibi yapardım.

      
      LDR    R0, =x              ; Load from Memory
      LDR    R1, [R0]            ; Load from Memory
      LDR    R2, [R0,#4]         ; Load  from Memory
      ADDS   R1, #1              ; Rd = Op1 + Op2
      ADDS   R2, #1              ; Rd = Op1 + Op2
      STR    R1, [R0]            ; Store to Memory
      STR    R2, [R0,#4]         ; Store to Memory
      BX     LR                  ; Branch to/from Thumb mode


Eğer 9 satırlık C kodunu 8 satıra indirebiliyorsak 100lerce satırda neler yapabiliriz gerisini sen düşün.

CM7 kullanmadığım için bu işlemcilerin pipeline conflict durumlarını bilmiyorum. Yukarıdaki kodda pipeline penalty yapmış olabilirim. Gene de asm yazım için atılıp tutulmasına gönlüm razı olmuyor.

C ile kodlarımızı çok hızlı ve çok anlaşılır yazabiliriz. ASM ile, çok yavaş ve çok anlaşılmaz fakat !!! çok hızlı koşan kodlar yazarız. Bütün olay bu.

Başkasının tüfeğini görmeyen kendi tabancasını top sanırmış.

-----------------

@mert3162

Bir kaç gün içinde daha önce açtığım 3D printer başlıklarının birinin altında, en son geliştirdiğim 3D yazıcı elektroniğinin videosunu yayınlayacağım.

Bu videoyu izledikten sonra LCD ve SD kart rutinlerini asm ile yazmak gerekiyor muymuş yoksa kütüphaneden çağırıp kullanmak yeterli miymiş buna çok rahat karar verirsin artık.

Bana e^st de diyebilirsiniz.   www.cncdesigner.com

z

Hocam farketmez. İşlemciler değiştikçe biz de yazım şeklimizi geliştiriyoruz.

ASM yazım şeklim 8051 de farklıydı, PIC'de farklı oldu DSPde farklı CM3 de çok farklı.

Dual load store işin içine girince de yazım şeklimiz de değişecek. Eğer program yazım şeklimizi değiştirmeyip mesela 8051'e kod yazar gibi yazarsak elbette işlemciden yeterince yararlanamayız.

Ayrıca asm kodlama yaparken fonksiyon gibi kısa parçalara değil daha büyük pencereden olaylara bakıp neler yapabiliriz ona bakıyoruz. Çok zahmetli bunu kabul ediyorum fakat C ile yapılan kodlamanın ASM den daha hızlı olacağına kesinlikle ve kesinlikle katılmıyorum.

Double load store işin içine girdimi çipe ısınıncaya kadar derhal bir macro yazar  ve yeni komut türetirim.

Mesela  DoubleLoad  R0, R1, R2,R3 dedimmi

   LDR R0,[R1]
   LDR R2,[R3]

işlemini yapar ve bunun tek cycle'da biteceğini bilirim.

ASM programcılıkda aynen işlemci gibi düşünürüz. İşin puştluğuna kaçmaya çalışırız. Eğer işin puştluğuna kaçamıyorsak o işlemciyi yeterince tanıyamamışız demektir.

Senin önermen ancak ayda yılda bir asm kodlama yapan için geçerli olur. Ben yatıp kalkıp CM3'e asm kod yazıyorum. Hızlı çalışan kod üretmede C falan dinlemem.

Irispiya mikis öğretilmez.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

z

Uğraştığım konular 10..20Mhz 16 bit MCUlarla zaten yapılabiliyor.  O yüzden işlemci seçiminde nerde duracağımı çok iyi biliyorum. Doğrudan kod atılıp çalıştırılabilecek CM3 kartını (işlemci değil PCBli kristalli vs kartı) 3$ ın altına alabiliyorsam daha neyin arayışına gireyim?

ASM konusundaki önyargıların hoşuma gitmiyor.  İmam osurursa cemaap mıçar.

Çok baba C derleyiciler kullanıyorsanız bu derleyicilerin oluşturulmasında çok iyi asm kodlamayı bilen ustaların büyük rolü var.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

z

http://www.direnc.net/STM32F103C8T6-Mini-Development-Board-ARDUINO,PR-22302.html

Burdaki kiti aliexpressden 10'lu alırsan fiyat bahsettiğim değerin de altına iniyor.

Asm ile kodlama yapan adamın asm için yavaş vs dememesi gerekir.

Büyük projelerde ekiplerle çalışmaktan ve işlerde C dayatılmasından kafan karışmış bence.

Ben mandaya kaymam.

Linked listle falan hiç işim olmuyor. Linked listi sadece çok çok yıllar önce PC'ye renkli editör yazarken kullanmıştım. Bir daha hiç işim olmadı.

Hocam ben genelde motor döndürüyorum. Bahsettiğin konular büyük veri yığınlarıyla ilgilenenler için değil mi?

Alıntı Yaphocam bir kaç compiler ın kaynak kodundan code generator kısmına ve optimizer kısmına bakarsan ASM kodlamayı bilen ustaların mı yoksa başka bazı şeyler ile uğraşan insanların mı büyük rolü var görürsün.

ASM kodlamayı bilen adamı içlerinden çekip alırsan ne olur?

Bana e^st de diyebilirsiniz.   www.cncdesigner.com

ido2323

Telefonun kapalı,  bu akşam müsayit isen uğrayayım diyorum.


LukeSkywalker


ipek

konu ile ilişkilendirmeyin.     ASM bilenlerin özgüvenlerine rahat tavırlarına,umursamazlıklarına hep hayran olmuşumdur...tabiki diğer diller e tü kaka değil.....

muhittin_kaplan

Hocam Aman ASM ile yazanlara can kurban, pythoncuları görseniz, sanırsınız teee fazadalar, diğerleri boş beleş işlerle uğraşıyorlar. python a laf demeye görün :)
z candır ;)

DEno_12

@z @gerbay sayın hocalarım,

Böyle atışacağınıza kodlarla atışsanız daha öğretici olmaz mı hepimiz için? İkinizin de ortak çalıştığı bir konuda basit bir kod öbeğini biriniz c ile biriniz asm ile yazsa da benchmark testi yapsak aynı işlemci üzerinde. Olmaz mı?

rck8942

Elektroniker für Betriebstechnik

Cemre.

Alıntı yapılan: DEno_12 - 08 Eylül 2016, 00:44:38
@z @gerbay sayın hocalarım,

Böyle atışacağınıza kodlarla atışsanız daha öğretici olmaz mı hepimiz için? İkinizin de ortak çalıştığı bir konuda basit bir kod öbeğini biriniz c ile biriniz asm ile yazsa da benchmark testi yapsak aynı işlemci üzerinde. Olmaz mı?
+1