8
votes

Intel Inspecteur signale une course de données dans ma mise en œuvre Spinlock

J'ai fait un spinlock très simple à l'aide des fonctions verrouillées sous Windows et l'a testée sur une CPU à double noyau (deux threads qui incrontent une variable);

Le programme semble fonctionner correctement (cela donne le même résultat à chaque fois, ce qui n'est pas le cas lorsqu'aucune synchronisation n'est utilisée), mais inspecteur parallèle Intel em> dit qu'il y a une condition de course à valeur + = j em> (voir le code ci-dessous). L'avertissement disparaît lorsque vous utilisez des sections critiques au lieu de mon spinlock. P>

est ma mise en œuvre de Spinlock correct ou non? C'est vraiment étrange, car toutes les opérations utilisées sont atomiques et disposent des barrières de mémoire appropriées et il ne faut pas conduire à des conditions de course. P>

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


0 commentaires

3 Réponses :


1
votes

Je suis à peu près sûr que cela 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); }
};


3 commentaires

Ce que vous avez proposé est à peu près la même chose avec ce que je fais, seulement que l'intort autour des spins de verrouillage est contenu dans la classe ... et cela serait un désavantage, car Raii ne peut plus être utilisé (la classe a également un destructeur qui libère la serrure automatiquement). Pensée, j'ai essayé ce que vous avez dit, et c'est la même chose: le programme fonctionne correctement, mais l'inspecteur Intel parallèle dit qu'il y a une condition de course. Peut-être que l'inspecteur a un bug? Mais probablement pas :(


Vous devez également utiliser longtemps pour commencer au lieu de faire la distribution explicite et, dans le constructeur, ne prends aucun paramètre et le démarrez simplement déverrouillé. Si la chose qui la crée que cela a besoin, il est verrouillé pour commencer, ils peuvent simplement le verrouiller après la création mais avant de le partager. @Igratian - Vous n'avez pas besoin de RAII dans ce cas car le destructeur n'a rien à nettoyer (c'est juste un long).


Édité. Je ne parviens pas à ajouter le déconstructeur ... comme la question ne justifie pas totalement correctement son code. J'essayais juste de résoudre sa question.



4
votes

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

Les outils d'analyse des nouveaux mécanismes de verrouillage ont tendance à être des outils statiques qui examinent chaque chemin possible grâce au code, la documentation de l'inspecteur parallèle implique qu'il exécute le code une fois.

Si vous souhaitez expérimenter avec de nouveaux mécanismes de verrouillage, l'outil le plus courant que j'ai vu utilisé dans la littérature académique est le Vérificateur de modèle de spin . Il y a aussi ESP , qui pourrait réduire l'espace d'état, mais je ne le fais pas savoir s'il a été appliqué aux problèmes simultanés, ainsi que le Workbench de mobilité qui donnerait une analyse si vous pouvez diviser votre problème dans Pi-calcul. L'inspecteur parallèle Intel ne semble rien comme compliqué que ces outils, mais plutôt conçu pour vérifier les problèmes couramment utilisés en utilisant des heuristiques.


0 commentaires

2
votes

Pour d'autres pauvres, dans une situation similaire pour moi: Intel fournit un ensemble d'inclut et de bibliothèques pour faire exactement ce genre de chose. Vérifiez dans le répertoire d'installation de l'inspecteur (vous verrez \ Inclure, \ lib32 et \ lib64 dans le répertoire d'installation) pour ces matériaux. Documentation sur la façon de les utiliser (à compter de juin 2018, bien que Intel ne se soucie de rien sur le respect des liens cohérents):

https://software.intel.com/en-us/inspector-user-Guide-Windows-apis-for-custom-synchronisation

Il y a 3 fonctions: xxx


1 commentaires

J'ai testé cela avec mon propre mutex Spin-Lock et cela fonctionne comme prévu (la course de données disparaît du rapport d'inspecteur parallèle)