Hatalar, hatalar, sorular - sayfa 2505

 

editördeki eski hata:

- dosyayı yeni bir adla kaydedin (örneğin: name_v1.2)
- imleci bir değişkenin (veya işlev çağrısının ) üzerine getirin
- alt+g'ye basın

- eski dosya açılır ve düzenleme ona atlar (

 
Vict :

Genel olarak, bunu beklemiyordum bile:

Kod biraz fazla karmaşık - Önbellek satırına sığmayan öğeye vurmaya ve doğrudan üzerine çekiçlemeye çalıştım, ancak işe yaramadı (gerçekten isteseydim muhtemelen yapardım ama yoruldum) bunun), ancak kodu fazla düzenlemedim. Ancak bu şekilde daha da etkileyici - önbellek satırına girmeyen bir öğe üzerinde 16 eklemeden yalnızca biri gerçekleştirilir, ancak yine de somut bir sonuç verir.

Not: bu durumda, tek bir kısa devreyi silerek değil, iki kısa devre ekleyerek RIGHT_ALIGNED yapmak daha objektiftir (bu şekilde her iki durum için iki önbellek satırı güncellemesi elde edeceğiz). Böylece hızlanma daha mütevazı olacak, ancak yine de yaklaşık 1,5 kat önemli olacak.

Üzgünüm, ama hizalamanın kullanımı nerede? Örnek başka bir şeyle ilgili.

PS Kodu yorumsuz ve ham haliyle yaymak muhataplara saygısızlıktır.

 

Doğru bir şekilde belirtildiği gibi, üçüncü taraf kitaplıklarında, özellikle de dotnet'te MQL yapı nesnelerini kullanmak için hizalama eklendi.

Dotnet kitaplıkları için destek eklenirken, paket yapılarının / sınıflarının alanlarının hizalanması eklendi.

Kısacası ve basit, şöyle çalışır:

Her türün (char, short, int, ...) varsayılan olarak kendi hizalaması (sırasıyla 1, 2, 4 bayt) vardır.
Bir yapı alanı için minimum iki hizalama seçilir: varsayılan ve kullanıcı tanımlı (paket aracılığıyla)

Aynı zamanda, paketlemeli nesnenin boyutu, dizideki nesnenin alanına adresleme her zaman "doğru" olacak şekilde ayarlanır (paket aracılığıyla belirtilir, varsayılan olarak 1 bayt)
İkincisi nedeniyle, paketinyapının boyutunu hizaladığı konusunda yanlış izlenim yaratılır - bu böyle değildir, alan adresleri hizalanır, bu da yapının boyutunun hizalanmasını gerektirir.



örneğin

 struct A pack( 8 )
  {
   double d;
   char    c;
  };

void OnStart ()
  {
   Print ( sizeof (A));
   
  }

Sonuç 16, böylece d'nin ilk alanının adresi her zaman 8 baytlık hizalanır

 
fxsaber :

Evde yapılan lansmanlar gözle görülür bir fark göstermedi.

Aklıma orijinal fikri getirdim (ilk kodda adresleri yanlış saydım). Zorlaştırmıyorsa, sonucu sizin için görmek ilginç olacaktır.

 #define WRONG_ALIGNED
#define CACHE_LINE_SIZE 64

struct Data {
#ifdef WRONG_ALIGNED
   ushort pad;
#else
   uint pad;
#endif
   uint ar[CACHE_LINE_SIZE/ sizeof ( int )+ 1 ];
};

#import "msvcrt.dll"
   long memcpy( uint &, uint &, long );
#import
#define getaddr(x) memcpy(x, x, 0 )

void OnStart ()
{
   Data data[ 32768 ];
   ZeroMemory (data);
   
   srand ( GetTickCount ());
   
   ulong start_time = GetMicrosecondCount ();
   
   for ( unsigned i = 0 ; i < 10000 ; ++ i) {
       int rndnum = rand ();
       while (++rndnum < 32768 ) {
         int index = int (CACHE_LINE_SIZE - getaddr(data[rndnum].ar[ 0 ]) % CACHE_LINE_SIZE) / sizeof ( int );
         ++ data[rndnum].ar[index];
         ++ data[rndnum].pad;
      }
   }
      
   Alert ( GetMicrosecondCount () - start_time);
   
   Print (data[ 100 ].ar[ 0 ]);
   Print (data[ 100 ].pad);
}
/*
WRONG_ALIGNED:
6206397
6185472

RIGHT_ALIGNED
4089827
4003213
*/
Özünde, WRONG_ALIGNED ile / olmadan, aynı şey olur - her birinde iki bitişik önbellek satırına yazarken (pad'e yazmak her zaman doğru adrestedir), tek fark WRONG_ALIGNED ile aşağıdaki durumlarda (her zaman değil) durumlar olmasıdır. ar'daki girişlerden biri, tamamen önbellek satırına girmeyen uint'e gider, yaklaşık 1,5 kat sabit bir farkım var.
 
Vict :

Aklıma orijinal fikri getirdim (ilk kodda adresleri yanlış saydım). Zorlaştırmıyorsa, sonucu sizin için görmek ilginç olacaktır.

Özünde, WRONG_ALIGNED ile / olmadan, aynı şey olur - her birinde iki bitişik önbellek satırına yazarken (pad'e yazmak her zaman doğru adrestedir), tek fark WRONG_ALIGNED ile aşağıdaki durumlarda (her zaman değil) durumlar olmasıdır. ar'daki girişlerden biri, tamamen önbellek satırına girmeyen uint'e gider, yaklaşık 1,5 kat sabit bir farkım var.

Lütfen bu satırla ne elde etmeye çalıştığınızı açıklayın? Önceki örnekte, bu çöp koduydu.

 int index = int (CACHE_LINE_SIZE - getaddr(data[rndnum].ar[ 0 ]) % CACHE_LINE_SIZE) / sizeof ( int );
 
Francuz :

Lütfen bu satırla ne elde etmeye çalıştığınızı açıklayın? Önceki örnekte, bu çöp koduydu.

Geçerli önbellek satırındaki (pad'in bulunduğu) konumumuzu bulun ve ar[] için öyle bir dizin alın ki onunla birlikte öğe bir sonraki önbellek satırındadır (belki öğe WRONG_ALIGNED ile iki önbellek satırındadır)

 
Vict :

Geçerli önbellek satırındaki (pad'in bulunduğu) konumumuzu bulun ve ar[] için öyle bir dizin alın ki onunla birlikte öğe bir sonraki önbellek satırındadır (belki öğe WRONG_ALIGNED ile iki önbellek satırındadır)

Şimdi yer değiştirmeden bahsediyoruz. Ama gösterdiğiniz, hayatta asla karşılaşmayacağınız tamamen sentetik bir örnek. Ve gerçek örneklerde, en iyi ihtimalle hız kazancı yaklaşık %1 olacaktır. Böyle yetersiz bir ivme uğruna, bahçeyi çitle çevirmemek gerekir.

Not Ayrıca, kaydın boyutunu yanlış hesapladınız.
 
Francuz :

Şimdi yer değiştirmeden bahsediyoruz. Ama gösterdiğiniz, hayatta asla karşılaşmayacağınız tamamen sentetik bir örnek. Ve gerçek örneklerde, en iyi ihtimalle hız kazancı yaklaşık %1 olacaktır. Böyle yetersiz bir ivme uğruna, bahçeyi çitle çevirmemek gerekir.

Hayır, bu çok gerçek bir örnek. İçinde, girişlerin sadece% 25'i önbellek hatlarının birleştiği "sorunlu" yerlerde gerçekleşir. çok mu Örneğin, bir dizi uzun çiftiniz var, bir önbellek satırına yalnızca 4 değer sığacak ve hizalama ile uğraşmazsanız (ve derleyici bunu sizin için yapmazsa), %25 alırsınız. sorunlu çiftler - tıpkı benim örneğimde olduğu gibi. Uyum için konuşan daha birçok nüans var, ancak onlar hakkında konuşmayacağım - konuyla ilgili kapsamlı bir bilgim yok.

Peki, sahibi bir barin.

Not Ayrıca, kaydın boyutunu yanlış hesapladınız.
Evet, hiç düşünmedim.
 
Vict :

Hayır, bu çok gerçek bir örnek. İçinde, girişlerin sadece% 25'i önbellek hatlarının birleştiği "sorunlu" yerlerde gerçekleşir. çok mu Örneğin, bir dizi uzun çiftiniz var, bir önbellek satırına yalnızca 4 değer sığacak ve hizalama ile uğraşmazsanız (ve derleyici bunu sizin için yapmazsa), %25 alırsınız. sorunlu çiftler - tıpkı benim örneğimde olduğu gibi. Uyum için konuşan daha birçok nüans var, ancak onlar hakkında konuşmayacağım - konuyla ilgili kapsamlı bir bilgim yok.

Peki, sahibi bir barin.

Bir kez daha söylüyorum, kasanın boyutunu karıştırıyorsunuz.

 
Francuz :

Bir kez daha söylüyorum, kasanın boyutunu karıştırıyorsunuz.

Savunmak