Epey süredir veri hizalama terimiyle hemhal olmaktayım ve kafamda bir soru işareti olarak yerini korumakta. Nihayet icraata geçerek bu terimin ne olduğu ve nerelerde kullanıldığı konusunda yaptığım ufak çaplı araştırmalarımdan aldığım notları sizlerle paylaşmak istedim.
Veri Hizalama Nedir?
Programlama dillerinde bir nesne (yani değişken) iki farklı özelliğe sahip bulunmakta. Bunlardan birincisi değeri ikincisi ise saklandığı yer yani adresi. Bilindiği üzere bilgisayarlar 2lik sayı sistemiyle çalışmakta ve 2’nin kuvveti sayılarla daha hızlı işlem yapabilmektedir. Veri hizalama terimi ise tam da burada bu söz konusu verinin adresinin 1, 2, 4 ve 8 ile tam olarak bölünebilmesi durumunu ifade eder. Yani veri hizalama ile bu veri nesnesini bellekte 1-bayt, 2-bayt, 4-bayt, 8-bayt veya 2’nin herhangi üsteli baytlık adreslere hizalamış oluruz. Örneğin adresi 12FEECh (ondalık 1244908) olan bir veriyi ele alalım. Bu verinin adresi 4 ile kalansız olarak bölünebildiğinden bu veri 4-bayt hızalanmış bir veridir (aslında veri 1 ve 2’ye de kalansız bölünebilmekte ancak kalansız bölünebildiği en büyük sayı 4’tür).
İşlemci bellekten bir baytlık okuma ya da yazma yapmaz. Bunun yerine belleğe bir seferde 2, 4, 8, 16 ya da 32 baytlık yığınlar halinde erişir. Bunun sebebi sınırı (her bir bayt grubunun başladığı yer) 4-bayt ya da 16-bayt olan bir adrese erişimin sınırı bir bayt olan bir adrese erişimden daha performanslı ve hızlı olmasıdır.
Aşağıdaki şekil CPU’nun 4-baytlık bir veri yığınına 4-baytlık bir bellek erişim granülaritesiyle (granülarite: CPU’nun bir seferde erişebildiği bayt sayısı) nasıl eriştiğini göstermektedir.
Eğer verinin 4-baytlık sınırı yanlış hizalanırsa İşlemci verinin 4-baytlık iki kümesini birden yükleyecek ve bunları birleştirmek için istenmeyen baytları kaydıracak dolayısıyla veriye erişmek için fazladan iş yapacaktır. Bu işlem de şüphesiz ki performansı düşürecek ve sadece veriyi bellekten almak için İşlemci gücünü boşa harcayacaktır.
Yapı Üyelerini Hizalama
32-bit x86 sistemlerde hizalama çoğunlukla veri tipinin boyutuyla aynıdır. Derleyici değişkenleri kendi boyutlarının sınırlarına göre hizalar. İşlemci hizalanmamış veriyi düzenli bir şekilde ele alacağından adresin hizalanmasına gerek kalmaz.
VERİ TİPİ | HİZALAMA (BAYT) |
---|---|
char | 1 |
short | 2 |
int | 4 |
float | 4 |
double | 4 veya 8 |
Ancak durum yapı, birlik veya sınıf nesneleri içerisindeki üye değişkenler söz konusu olunca biraz farklılaşır. Performans kayıplarından kaçınmak için yapı (birlik veya sınıf da olabilir) üye değişkenleri, bu üye değişkenlerinden herhangi birinin en yüksek baytına hizalanmalıdır. Örneğin 1 char (1 bayt) ve 1 int (4 bayt) üye değişkenine sahip bir yapımız olduğunu düşünelim. Hizalama ile derleyici bu iki değişkenin arasına 3 baytlık bir boşluk daha koyacak ve bundan dolayı da değişkenlerin normalde 5 bayt olması gereken toplam boyutu 8 bayt olacaktır. Böylece bu yapının adresini 4’e kalansız olarak bölünebilir duruma getirmiş oluruz. Bu işleme yapı üyelerinin hizalanması diyoruz. Haliyle hizalama işlemi yapının boyutunu da artıracaktır.
// boyut = 2 bayt, hizalama = 1-bayt, adres 1'e bölünebilir
struct S1 {
char m1; // 1-bayt
char m2; // 1-bayt
};
// boyut = 4 bayt, hizalama = 2-bayt, adres 2'ye bölünebilir
struct S2 {
char m1; // 1-bayt
// derleyici burada 1 baytlık boşluk bırakır
short m2; // 2-bayt
};
// boyut = 8 bayt, hizalama = 4-bayt, adres 4'e bölünebilir
struct S3 {
char m1; // 1-bayt
// derleyici burada 3 baytlık boşluk bırakır
int m2; // 4-bayt
};
// boyut = 16 bayt, hizalama = 8-bayt, adres 8'e bölünebilir
struct S4 {
char m1; // 1-bayt
// derleyici burada 7 baytlık boşluk bırakır
double m2; // 8-bayt
};
// boyut = 16 bayt, hizalama = 8-bayt, adres 8'e bölünebilir
struct S5 {
char m1; // 1-bayt
// derleyici burada 3 baytlık boşluk bırakır
int m2; // 4-byte
double m2; // 8-byte
};
Yapı birlik veya sınıf üyeleri için farklı paket hizalama metotlarını “pragma” makro direktifiyle belirtebilirsiniz.
// 1-bayt yapı üye hizalama
// boyut = 9 bayt, hizalama = 1-bayt, bu yapı üyeleri arasında boşluk yok
#pragma pack(push, 1)
struct S6 {
char m1; // 1-byte
double m2; // 8-byte
};
#pragma pack(pop)
Bir de SSE için veri hizalama konusu var ancak bu konuyu başka bir yazıya bırakarak bu yazımı burada tamamlamak istiyorum. Herkese iyi ve verimli çalışmalar.
İlk Yorumu Siz Yapın