Question

J'ai fait une spinlock très simple en utilisant les fonctions Interlocked dans Windows et testé sur un processeur dual-core (deux threads qui incrémente une variable);

Le programme semble fonctionner OK (il donne le même résultat à chaque fois, ce qui est le cas en l'absence de synchronisation est utilisé), mais Intel Parallel Inspector dit qu'il ya une condition de course à < em> valeur + = j (voir le code ci-dessous). L'avertissement disparaît lorsque vous utilisez les sections critiques au lieu de mon SpinLock.

Ma mise en œuvre de SpinLock correcte ou non? Il est vraiment étrange, parce que toutes les opérations utilisées sont atomiques et ont les barrières de mémoire appropriées et il ne devrait pas conduire à des conditions de course.

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); }
};

Le programme de 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;
}
Était-ce utile?

La solution

documentation de l'inspecteur en parallèle pour course de données suggère d'utiliser une section critique ou d'un mutex pour fixer des courses sous Windows. Il n'y a rien dans ce qui suggère que l'inspecteur parallèle sait reconnaître tout autre mécanisme de verrouillage que vous pourriez inventer.

Outils d'analyse de nouveaux mécanismes de verrouillage ont tendance à être des outils statiques qui regardent tous les chemins possibles à travers le code, la documentation de l'inspecteur parallèle implique qu'il exécute le code une fois.

Si vous voulez expérimenter avec de nouveaux mécanismes de verrouillage, l'outil le plus commun que je l'ai vu utilisé dans la littérature académique est le modèle Spin vérificateur . Il y a aussi ESP , ce qui pourrait réduire l'espace d'état, mais je ne savoir si elle a été appliquée à des problèmes simultanés, et aussi le table de travail de la mobilité qui pourrait donner une analyse si vous pouvez couch votre problème pi-calcul. Intel Parallel Inspector ne semble pas quelque chose comme aussi compliqué que ces outils, mais conçu pour vérifier les problèmes fréquemment rencontrés en utilisant heuristiques.

Autres conseils

Pour d'autres pauvres gens dans une situation semblable à moi: Intel fournit un ensemble de bibliothèques et comprend pour faire exactement ce genre de chose. Vérifiez dans le répertoire d'installation de l'inspecteur (vous verrez \ include \ lib32 et \ lib64 dans le répertoire d'installation) pour les matériaux. Documentation sur la façon de les utiliser (en Juin 2018, mais Intel ne se soucie pas sur les liens en gardant constante):

https: // logiciel .intel.com / en-us / windows-Guide-utilisateur-inspecteur-apis-pour-mesure la synchronisation

Il y a 3 fonctions:

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

Je suis assez sûr qu'il devrait être mis en œuvre comme suit:

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

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

   void Unlock() { InterlockedExchange(&lockValue, 0); }
};
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top