L1 Önbelleği Maliyetini Bayan nedir?
Edit: Referans amaçlı eğer herkes bu soruya tökezledi değilseniz, Igor Ostrovsky great post yaklaşık bir önbellek özlüyor yazdı. Çeşitli konularda tartışır ve örnek sayıları verilmiştir.Düzenleme Sonunda
Bazı test <long story goes here>
yaptım ve eğer bir performans farkı önbellek özlüyor kaynaklanıyor merak ediyorum. Aşağıdaki kodu sorun gösterir ve kritik zamanlama kısmı için aşağı kaynar. Aşağıdaki kodu rastgele hafıza ziyaret ve artan sipariş adresi daha sonra bu döngüler bir çift var.
Bir Linux (gcc –Os) üzerinde XP makine (VS2005 ile derlenmiş: /O2 cl) ve koştum. Her ikisi de benzer zamanlarda üretti. Bu kez, milisaniye cinsinden. Tüm döngüleri çalışan ve optimize değil inanıyorum (aksi takdirde aday olacağını“”) anında.
*** Testing 20000 nodes Total Ordered Time: 888.822899 Total Random Time: 2155.846268
Bu sayıların bir anlamı? Fark L1 önbellek özlüyor nedeniyledir ya da başka bir şey mi oluyor? 20,000^2 bellek erişimleri vardır ve her bir önbellek bir bayan olsaydı, o Bayan başına yaklaşık 3.2 nanosaniye. (P4) üzerinde test ettim makine 3.2 GHz ve sanıyorum XP (ama bilmiyorum) 32 KB L1 önbellek ve 512 KB L2 var. 20,000 girişleri ile (80KB), L2 sayıda özlüyor yoktur sanırım. Bu (3.2*10^9 cycles/second) * 3.2*10^-9 seconds/miss) = 10.1 cycles/miss
olur. Bana yüksek gibi görünüyor. Belki de değil, belki de matematiğim kötü. Ölçüm önbellek VTune ile özlüyor çalıştım ama bir BSOD aldım. Ve şimdi lisans sunucusuna bağlanmak için alamıyorum (grrrr).
typedef struct stItem
{
long lData;
//char acPad[20];
} LIST_NODE;
#if defined( WIN32 )
void StartTimer( LONGLONG *pt1 )
{
QueryPerformanceCounter( (LARGE_INTEGER*)pt1 );
}
void StopTimer( LONGLONG t1, double *pdMS )
{
LONGLONG t2, llFreq;
QueryPerformanceCounter( (LARGE_INTEGER*)&t2 );
QueryPerformanceFrequency( (LARGE_INTEGER*)&llFreq );
*pdMS = ((double)( t2 - t1 ) / (double)llFreq) * 1000.0;
}
#else
// doesn't need 64-bit integer in this case
void StartTimer( LONGLONG *pt1 )
{
// Just use clock(), this test doesn't need higher resolution
*pt1 = clock();
}
void StopTimer( LONGLONG t1, double *pdMS )
{
LONGLONG t2 = clock();
*pdMS = (double)( t2 - t1 ) / ( CLOCKS_PER_SEC / 1000 );
}
#endif
long longrand()
{
#if defined( WIN32 )
// Stupid cheesy way to make sure it is not just a 16-bit rand value
return ( rand() << 16 ) | rand();
#else
return rand();
#endif
}
// get random value in the given range
int randint( int m, int n )
{
int ret = longrand() % ( n - m 1 );
return ret m;
}
// I think I got this out of Programming Pearls (Bentley).
void ShuffleArray
(
long *plShuffle, // (O) return array of "randomly" ordered integers
long lNumItems // (I) length of array
)
{
long i;
long j;
long t;
for ( i = 0; i < lNumItems; i )
plShuffle[i] = i;
for ( i = 0; i < lNumItems; i )
{
j = randint( i, lNumItems - 1 );
t = plShuffle[i];
plShuffle[i] = plShuffle[j];
plShuffle[j] = t;
}
}
int main( int argc, char* argv[] )
{
long *plDataValues;
LIST_NODE *pstNodes;
long lNumItems = 20000;
long i, j;
LONGLONG t1; // for timing
double dms;
if ( argc > 1 && atoi(argv[1]) > 0 )
lNumItems = atoi( argv[1] );
printf( "\n\n*** Testing %u nodes\n", lNumItems );
srand( (unsigned int)time( 0 ));
// allocate the nodes as one single chunk of memory
pstNodes = (LIST_NODE*)malloc( lNumItems * sizeof( LIST_NODE ));
assert( pstNodes != NULL );
// Create an array that gives the access order for the nodes
plDataValues = (long*)malloc( lNumItems * sizeof( long ));
assert( plDataValues != NULL );
// Access the data in order
for ( i = 0; i < lNumItems; i )
plDataValues[i] = i;
StartTimer( &t1 );
// Loop through and access the memory a bunch of times
for ( j = 0; j < lNumItems; j )
{
for ( i = 0; i < lNumItems; i )
{
pstNodes[plDataValues[i]].lData = i * j;
}
}
StopTimer( t1, &dms );
printf( "Total Ordered Time: %f\n", dms );
// now access the array positions in a "random" order
ShuffleArray( plDataValues, lNumItems );
StartTimer( &t1 );
for ( j = 0; j < lNumItems; j )
{
for ( i = 0; i < lNumItems; i )
{
pstNodes[plDataValues[i]].lData = i * j;
}
}
StopTimer( t1, &dms );
printf( "Total Random Time: %f\n", dms );
}
CEVAP
Süre veremem teklif bir cevap olsun ya da olmasın sayıların anlamı (değilim iyi usta önbellek gecikmeleri, ama rekoru ~10 döngüsü L1 önbellek özlüyor hemen hemen öyle), ben teklif Cachegrind gibi bir araç için yardım gerçekten görmek farklar önbellek performans arasında 2 testleri.
Cachegrind önbellek ve şube vurur Valgrind bir aracı (güçler her zaman güzel memcheck bu çerçeve)/özlüyor. Sen kaç/aslında programda alıyorsanız özlüyor bir fikir verecektir.
Python yumurta önbelleği (PYTHON_EGG_C...
Olay köpüren ve yakalama nedir?...
Scala'nin verimi nedir?...
(Saat:Dakika:Saniye:Milisaniye) zaman ...
Bool için printf biçim belirteci nedir...