Global değişken ile yerel değişken arasındaki hız farkı

Başlatan izturk, 13 Ekim 2015, 21:33:55

izturk

Merhaba arkadaşlar

Z hocamın stm32 derslerine bakıyordum. baştaki örneklerden led yakıp söndürme uygulamasında denemeler yaparken birşey dikkatimi çekti.

for döngüsü içerisindeki a değişkenini main fonksiyonunun dışında tanımladığımda ledler yavaş yanıp sönüyor. a değişkenini main içerisinde tanımlarsam ledler daha hızlı yanıp sönüyor. bunun sebebi nedir?

yavaş:
int a=0;
int main()
{
	
    while(1)
      {


				GPIOD->ODR= 0x0000F000;     // Ledler yansin
                                for(a=0;a<1000000;a++); 
				GPIOD->ODR= 0x00000000;     // Ledler sonsun
				for(a=0;a<1000000;a++);

} 
}
// Programin sonu.



hızlı:
int main()
{
	
    while(1)
      {
int a=0;

				GPIOD->ODR= 0x0000F000;     // Ledler yansin
        for(a=0;a<1000000;a++); 
				GPIOD->ODR= 0x00000000;     // Ledler sonsun
				for(a=0;a<1000000;a++);

} 
}
// Programin sonu.

İyi Çalışmalar.


Gökhan BEKEN

Özel mesaj okumuyorum, lütfen göndermeyin.

erenbasturk


optimizasyon seviyesi 0'da derliyorsan external ve automatic sınıf 'ları için farklı assembly kodlar oluşabilir. optimizasyon seviyesi 3'e aldığında bu durumun oluşmaması gerekir. assembly kodlarını incele kısacası


ehliseyf

Alıntı yapılan: erenbasturk - 14 Ekim 2015, 00:31:26
optimizasyon seviyesi 0'da derliyorsan external ve automatic sınıf 'ları için farklı assembly kodlar oluşabilir. optimizasyon seviyesi 3'e aldığında bu durumun oluşmaması gerekir. assembly kodlarını incele kısacası
Bahsettiğiniz seviyeyi biraz anlatır mısınız ? ilk defa duyduğum bir durum, öğrenmek isterim.
Code'm mu oturturum !

erenbasturk

Alıntı yapılan: ehliseyf - 14 Ekim 2015, 10:06:14
Bahsettiğiniz seviyeyi biraz anlatır mısınız ? ilk defa duyduğum bir durum, öğrenmek isterim.

optimizasyon seviyesi 0'da derlediğiniz zaman bir çok optimizasyon bayragını pasif duruma getiriyorsunuz. optimizasyonlar'da yer, çalıştırma hızı ve bunun gibi bir çok optimizasyon opsiyonları var.  sizin tanımladığınız bir global değişkenin işlenmesi için oluşturulan kodlar ile local degişkenin işlenmesi için oluşturulan kodlar optimizasyon seviyesi 0'da farklılık gösterebiliyor. buradaki arkadaşın sıkıntısıda for döngüsünü işlemek için oluşturulan kodların bir programda daha fazla assembly kod oluşmasından kaynaklanıyor. eğer optimizasyon seviyesi 3'e  alırsanız, kodlar optimize edilmiş bir şekilde oluşuyor genede küçük farklılıklar olabiliyor.

Gökhan BEKEN

#5
Evet denedim şimdi,
optimizasyon level 3 iken global de olsa yerel de olsa farketmiyor süre: 35.7 ms
optimizasyon level 0 iken a değişkeni global tanımlandı, süre: 107 ms
optimizasyon level 0 iken a değişkeni local tanımlandı, süre: 35.7 ms
Özel mesaj okumuyorum, lütfen göndermeyin.

yamak

Bunun optimizasyonla çok bi alakası yok aslında hatta optimizsayon level 3'te iken oradaki for döngüleri komple silinebilir.
Değişken local tanımlandığında aşağıdaki gibi assembly kodu üretiliyor:
    24:             while(1) 
    25:       { 
    26:  
0x0800026A E012      B             0x08000292
    27:                                 GPIOD->ODR= 0x0000F000;     // Ledler yansin 
0x0800026C F44F4170  MOV           r1,#0xF000
0x08000270 4A08      LDR           r2,[pc,#32]  ; @0x08000294
0x08000272 6011      STR           r1,[r2,#0x00]
    28:         for(a=0;a<1000000;a++); 
0x08000274 2000      MOVS          r0,#0x00
0x08000276 E000      B             0x0800027A
0x08000278 1C40      ADDS          r0,r0,#1
0x0800027A 4907      LDR           r1,[pc,#28]  ; @0x08000298
0x0800027C 4288      CMP           r0,r1
0x0800027E DBFB      BLT           0x08000278
    29:                                 GPIOD->ODR= 0x00000000;     // Ledler sonsun 
0x08000280 2100      MOVS          r1,#0x00
0x08000282 4A04      LDR           r2,[pc,#16]  ; @0x08000294
0x08000284 6011      STR           r1,[r2,#0x00]
    30:                                 for(a=0;a<1000000;a++); 
0x08000286 2000      MOVS          r0,#0x00
0x08000288 E000      B             0x0800028C
0x0800028A 1C40      ADDS          r0,r0,#1
0x0800028C 4902      LDR           r1,[pc,#8]  ; @0x08000298
0x0800028E 4288      CMP           r0,r1
0x08000290 DBFB      BLT           0x0800028A

Şimdi burada olan olay kabataslak şu şekilde:
a değişkeni ilk olarak r0 register'ına yükleniyor ve r0 1000000 e kadar  birer birer artırlıyor ve r0 ın değeri 1000000 olunca döngü bitiyo.Yani tüm işlemler r0 üzerinden yapılıyor.
Fakat değişken global olduğunda üretilen assembly koduna bakacak olursak:
    24:             while(1) 
    25:       { 
    26:  
0x08000268 E021      B             0x080002AE
    27:                                 GPIOD->ODR= 0x0000F000;     // Ledler yansin 
0x0800026A F44F4070  MOV           r0,#0xF000
0x0800026E 4910      LDR           r1,[pc,#64]  ; @0x080002B0
0x08000270 6008      STR           r0,[r1,#0x00]
    28:         for(a=0;a<1000000;a++); 
0x08000272 2000      MOVS        r0,#0x00//r0 a 0 yükleniyo.
0x08000274 490F      LDR           r1,[pc,#60]  ; @0x080002B4//a değişkeninin ramdeki adresi flash'tan r1 register'ına yükleniyor
0x08000276 6008      STR           r0,[r1,#0x00]//r0 daki değeri a değişkeninin adresine yazılıyo
0x08000278 E004      B             0x08000284
0x0800027A 480E      LDR           r0,[pc,#56]  ; @0x080002B4
0x0800027C 6800      LDR           r0,[r0,#0x00]
0x0800027E 1C40      ADDS         r0,r0,#1
0x08000280 490C      LDR           r1,[pc,#48]  ; @0x080002B4
0x08000282 6008      STR           r0,[r1,#0x00]
0x08000284 480B      LDR           r0,[pc,#44]  ; @0x080002B4
0x08000286 6800      LDR           r0,[r0,#0x00]
0x08000288 490B      LDR           r1,[pc,#44]  ; @0x080002B8
0x0800028A 4288      CMP           r0,r1
0x0800028C DBF5      BLT           0x0800027A
    29:                                 GPIOD->ODR= 0x00000000;     // Ledler sonsun 
0x0800028E 2000      MOVS          r0,#0x00
0x08000290 4907      LDR           r1,[pc,#28]  ; @0x080002B0
0x08000292 6008      STR           r0,[r1,#0x00]
    30:                                 for(a=0;a<1000000;a++); 
0x08000294 4907      LDR           r1,[pc,#28]  ; @0x080002B4
0x08000296 6008      STR           r0,[r1,#0x00]
0x08000298 E004      B             0x080002A4
0x0800029A 4806      LDR           r0,[pc,#24]  ; @0x080002B4
0x0800029C 6800      LDR           r0,[r0,#0x00]
0x0800029E 1C40      ADDS          r0,r0,#1
0x080002A0 4904      LDR           r1,[pc,#16]  ; @0x080002B4
0x080002A2 6008      STR           r0,[r1,#0x00]
0x080002A4 4803      LDR           r0,[pc,#12]  ; @0x080002B4
0x080002A6 6800      LDR           r0,[r0,#0x00]
0x080002A8 4903      LDR           r1,[pc,#12]  ; @0x080002B8
0x080002AA 4288      CMP           r0,r1
0x080002AC DBF5      BLT           0x0800029A

Burada ise olaylar şöyle işliyo:
a nın değeri ram'den okunuyor bir artırılıyor ve ram'e tekrar yazılıyor.Sonra yine karşılaştırma yaapılacağı zaman ram'deki değeri okunup karşılaştırılıyor.Yani tüm işlemler bi kere register'a okunup yapılıyor her seferinde adres üzerinden yapılıyor.
Bunu sebebi ise global tanımlı değişkenin değeri programın herhangi bir yerinden her an değişebilileceği için.Örneği for döngüsü işlenirken bir interrupt gelip a'nın değerin değiştirebilir.Bu durumun önüne geçmek için derleyici bu şekilde bir önlem alıyor.