2012-09-25 17 views
10

Modifica: ST non consente di pubblicare più di due collegamenti per principianti. Ci scusiamo per i riferimenti mancanti.Verifica senza blocco per la modifica di uno stato condiviso globale in C utilizzando l'allineamento Cache-Line

Sto provando a ridurre l'overhead di blocco in un'applicazione C in cui rilevare le modifiche su uno stato globale è rilevante per le prestazioni. Anche se ultimamente ho letto molto sull'argomento (ad esempio molto da H. Sutter e molti altri) non sono sicuro della mia implementazione. Vorrei utilizzare una combinazione di un CAS come il funzionamento e DCL per un controllo su una variabile globale Cache-Line Allineati, evitando così falsi-sharing, per aggiornare filettatura dati locali da dati condivisi tra più thread. La mia mancanza di fiducia è dovuto principalmente alla

  1. me non riuscendo a interpretare la documentazione GNU su Type-Attributes
  2. io non sembrano essere in grado di trovare alcuna documentazione e gli esempi che potrei facilmente si traducono in C, come ad esempio aligning- a-cache-line-e-sapere-the-cache-line-size su ST o 1 (anche se sembra rispondere alla mia domanda un po 'io non sono fiducioso con la mia implementazione)
  3. la mia esperienza con C è limitato

Le mie domande:

  1. il tipo di attributi documentazione afferma:

    Questo attributo specifica un allineamento minimo (in byte) per le variabili del tipo specificato. Ad esempio, le dichiarazioni:

    (vedi documenti di attributi di dichiarazione)

    forza il compilatore di assicurare (per quanto possibile) che ogni variabile il cui tipo è struct S o saranno assegnati more_aligned_int e allineato almeno su un limite 8-byte. Su un SPARC, avente tutte le variabili di tipo struct S allineato 8-byte confini consente al compilatore di utilizzare la LDD e std (carico di doppia e memorizzare) istruzioni per copiare una variabile di tipo struct S all'altro, migliorando così l'efficienza di runtime .

    Vuol dire che l'inizio del struct S o more_aligned_int sarà sempre allineato al 8-byte confine? Ciò non significa che i dati verranno riempiti per utilizzare esattamente 64 byte, giusto?

  2. Presupposto 1.È vero che ogni caso di struct cache_line_aligned (vedi codice Esempio 1 sotto) allinea il 64-byte confini e utilizzare esattamente una cache di riga (supponendo cache-linee sono 64 bytes lunghezza)

  3. Uso typedef per la dichiarazione di tipo no alterare la semantica di __attribute__ ((aligned (64))) (vedi codice Esempio 2 sotto)

  4. non ho bisogno di usare aligned_malloc quando si crea un'istanza della struct se struct è dichiarato con __attribute__ ...

// Example 1 
struct cache_line_aligned { 
 int version; 
 char padding[60]; 
} __attribute__ ((aligned (64))); 

// Example 2 
typedef struct { 
 int version; 
    // place '__attribute__ ((aligned (64)))' after 'int version' 
    // or at the end of the declaration 
 char padding[60]; 
} cache_line_aligned2 __attribute__ ((aligned (64))); 

E infine uno schizzo di una funzione che utilizza l'approccio allineato di cache-line per controllare in modo efficiente se stato globale è stato modificato da qualche altro thread:

void lazy_update_if_changed(int &t_version, char *t_data) { 
    // Assuming 'g_cache_line_aligned' is an instance of 
    // 'struct cache_line_aligned' or 'struct cache_line_aligned2' 
    // and variables prefixed with 't_' being thread local 
    if(g_cache_line_aligned.version == t_version) { 
    // do nothing and return 
    } else { 
    // enter critical section (acquire lock e.g. with pthread_mutex_lock) 
    t_version = g_cache_line_aligned.version 
    // read other data that requires locking where changes are notified 
    // by modifying 'g_cache_line_aligned.version', e.g. t_data 
    // leave critical section 
    } 
} 

Ci scusiamo per il lungo post.

Grazie!

risposta

7

Quando si definisce un tipo allineato, ad esempio, allineato ai limiti di 8 byte, il compilatore deve rendere il tipo un multiplo dell'allineamento (in questo caso, un multiplo di 8 byte) di dimensioni per riempimento.

La logica è semplice. Supponiamo di voler definire una matrice di quel tipo allineato. Naturalmente, ogni elemento dovrebbe essere allineato. Ecco perché potrebbe esserci il padding.

Ecco una piccola dimostrazione:

#include <stdio.h> 

struct cache_line_aligned { 
    int version; 
// char padding[60]; 
} __attribute__ ((aligned (64))); 

int main(void) 
{ 
    struct cache_line_aligned s; 
    struct cache_line_aligned a[2]; 
    printf("sizeof(struct cache_line_aligned) = %d\n", (int)sizeof(struct cache_line_aligned)); 
    printf("sizeof(s) = %d\n", (int)sizeof(s)); 
    printf("sizeof(a[0]) = %d\n", (int)sizeof(a[0])); 
    printf("sizeof(a) = %d\n", (int)sizeof(a)); 
    return 0; 
} 

uscita (ideone):

sizeof(struct cache_line_aligned) = 64 
sizeof(s) = 64 
sizeof(a[0]) = 64 
sizeof(a) = 128 

Se si crea un'istanza di struct cache_line_aligned non in modo dinamico (IOW, non tramite malloc() e simili), proprio come nel codice sopra, sarà allineato.

Lo standard C (dal 1999) stabilisce per malloc(), calloc() e realloc():

The pointer returned if the allocation succeeds is suitably aligned so that 
it may be assigned to a pointer to any type of object and then used to 
access such an object or an array of such objects in the space allocated 
(until the space is explicitly deallocated). 

Dove any type of object non include artificialmente allineati tipi/imbottite come struct sopra perché non c'è nulla di simile nella __attribute__ ((aligned (64))) Standard C Questa è un'estensione GNU qui. Per oggetti allocati dinamicamente con allineamento arbitrario, è necessario utilizzare la funzione di allocazione della memoria appropriata o eseguire manualmente l'allineamento (allocando più memoria e quindi "allineare" il valore del puntatore).

+0

Cheers! questo ha chiarito molto bene le cose. Non ho pensato di usare sizeof per verificare l'allineamento! Lo ricorderò questo. Che dire delle strutture allineate allocate dinamicamente? 'Align_malloc' farà il lavoro? – instilled

+0

Probabilmente lo farà. Leggi la sua documentazione per essere sicuro. –

+0

Sicuro! Lo farà. Grazie ancora per la brillante risposta. – instilled