Domanda

Ho fatto una molto semplice spinlock utilizzando le funzioni interbloccate in Windows e testato su una CPU dual-core (due thread che incrementano una variabile);

Il programma sembra funzionare bene (dà lo stesso risultato ogni volta, che non è il caso in cui non viene utilizzato alcun la sincronizzazione), ma Intel Parallel Inspector dice che c'è una condizione di competizione a < em> valore + = j (vedi il codice qui sotto). L'avvertimento scompare quando si utilizza sezioni critiche al posto della mia SpinLock.

È la mia implementazione di SpinLock corretto oppure no? E 'davvero strano, perché tutte le operazioni utilizzate sono atomiche e hanno le barriere di memoria corretto e non dovrebbe portare a condizioni di gara.

class SpinLock
{
   int *lockValue;
   SpinLock(int *value) : lockValue(value) { }

   void Lock() {
      while(InterlockedCompareExchange((volatile LONG*)lockValue, 1, 0) != 0) {
          WaitABit();
      }
   }

   void Unlock() { InterlockedExchange((volatile LONG*)lockValue, 0); }
};

Il programma di test:

static const int THREADS = 2;
HANDLE completedEvents[THREADS];
int value = 0;
int lock = 0; // Global.

DWORD WINAPI TestThread(void *param) {
    HANDLE completed = (HANDLE)param;
    SpinLock testLock(&lock);

    for(int i = 0;i < 1000*20; i++) {
        for(int j = 0;j < 10*10; j++) {
            // Add something to the variable.
            testLock.Lock();
            value += j;
            testLock.Unlock();
        }
    }
    SetEvent(completed);
}

int main() {
   for(int i = 0; i < THREADS; i++) {
        completedEvents[i] = CreateEvent(NULL, true, false, NULL);
   }
   for(int i = 0; i < THREADS; i++) {
        DWORD id;
        CreateThread(NULL, 0, TestThread, completedEvents[i], 0, &id);
   }

   WaitForMultipleObjects(THREADS, completedEvents, true, INFINITE);
   cout<<value;
}
È stato utile?

Soluzione

documentazione dell'ispettore parallela per corsa dati suggerisce di utilizzare una sezione critica o di un mutex per truccare le gare su Windows. Non c'è niente in esso che suggerisce che l'ispettore parallelo sa riconoscere qualsiasi altro meccanismo di blocco si potrebbe inventare.

Strumenti per l'analisi dei meccanismi di bloccaggio nuovi tendono ad essere statica strumento che guardano ogni possibile percorso attraverso il codice, documentazione dell'ispettore Parallel implica che esso esegue il codice una volta.

Se si vuole sperimentare con nuovi meccanismi di bloccaggio, lo strumento più comune che ho visto usare nella letteratura accademica è la Spin model checker . C'è anche ESP , che potrebbe ridurre lo spazio di stato, ma non lo faccio sapere se è stata applicata a problemi concomitanti, e anche il rel mobilità banco di lavoro che darebbe un'analisi se potete divano il problema in pi-calcolo. Intel Parallel Inspector non sembra nulla di simile così complicato come questi strumenti, ma piuttosto progettato per verificare la presenza di problemi che si verificano comunemente che utilizzano euristica.

Altri suggerimenti

Per le altre persone povere in una situazione simile a me: Intel fornisce una serie di include e librerie per fare esattamente questo genere di cose. Controllare nella directory di installazione Inspector (vedrete \ include \ lib32 e \ lib64 nella directory di installazione) per quei materiali. Documentazione su come usarli (a partire da giugno 2018, anche se Intel non importa nulla di mantenere collegamenti coerenti):

https: // software .intel.com / it-IT / ispettore user-guida-windows-API-per-custom-sincronizzazione

Ci sono 3 funzioni:

void __itt_sync_acquired(void *addr)
void __itt_sync_releasing(void *addr)
void __itt_sync_destroy(void *addr)

Sono abbastanza sicuro che dovrebbe essere attuato nel seguente modo:

class SpinLock
{
   long lockValue;
   SpinLock(long value) : lockValue(value) { }

   void Lock() {
      while(InterlockedCompareExchange(&lockValue, 1, 0) != 0) {
          WaitABit();
      }
   }

   void Unlock() { InterlockedExchange(&lockValue, 0); }
};
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top