J'ai un code qui est comme suit (code simplifié): Ce code fonctionne bien, mais si je veux le faire parallèlement en utilisant OMM parallèle pour, je reçois une erreur sur sortie.push_back et il semble que lors du redimensionnement du vecteur, la mémoire corrompue. P> Quel est le problème et comment puis-je résoudre le problème? p> Comment puis-je assurer un seul fil d'insertion nouvel article dans le vecteur à tout moment? p> p>
6 Réponses :
Cependant, étant donné que les éléments ne dépendent pas l'un de l'autre, il serait très raisonnable de code> redimensionner code> le vecteur et modifier des éléments à l'intérieur de la boucle séparément: p> Étant donné que l'accès direct à l'aide de "Comment puis-je m'assurer qu'un seul fil insérant un nouvel élément dans le vecteur à tout moment?" em> p> Vous n'avez pas besoin de. Les threads modifieront différents éléments (qui résident dans différentes parties de la mémoire). Il vous suffit de vous assurer que l'élément que chaque fil tente de modifier est le bon. P> p> std :: vecteur code> 's
push_back code> ne peut pas garantir un comportement correct lorsqu'il est appelé de manière concomitante comme si vous faites maintenant (il n'y a pas de sécurité) .
opérateur [] code> ne dépend pas d'autres membres de
std :: vecteur code> qui pourrait causer des incohérences entre les fils. Cependant, strong> Cette solution peut encore avoir besoin d'une synchronisation explicite (c'est-à-dire à l'aide d'un mécanisme de synchronisation telle que Mutex) qui garantira qu'une valeur correcte du
k code> sera utilisée. P>
Cela ne fonctionne pas car le nombre d'éléments de sortie n'est pas identique à l'entrée. S'il vous plaît regarder si (isgoodmatch ())
@mans: Voir mon édition. Vous pouvez toujours compter sur sortie.Size () code> <=
entrée.Size () code>
Vous devez toujours faire une sortie [k] = newvalues; k ++; code> atomique, ou il y a une condition de course, car deux threads peuvent tous deux écrire sur le même
k code>.
@Antonguryanov: Bien que cela sonne parfaitement raisonnable, je pense que l'incrémentation d'une variable int code> de cette manière doit être traitée par OMP (mais je dois admettre que je ne suis pas sûr de)
@LIHO: Même si k ++ code> est atomique, il ne veut pas que si
sortie [k] = newvalues code> est threadsafe et
k ++ code> est atomique, alors
sortie [k] = newvalues; k ++; code> est atomique. Deux threads pourraient tous les deux voir la même valeur de
k code> dans la ligne du Fist avant l'un d'entre eux l'incromption dans la deuxième ligne.
@Stevejessop: Oui, je comprends le point d'Anton, mais ... êtes-vous sûr que cela n'est pas traité interne par OMP?
@Liho: Je ne suis pas certain I> que ce n'est pas, je n'ai jamais utilisé OMP. Mais cela semble être une prétention assez importante pour moi, que je considérerais improbable à moins que quelqu'un soit sûr. Voulez-vous dire que OMPT détectera toutes les utilisations de k code> dans la boucle et rendra le bloc de code du premier au dernier dans une opération atomique? Pour une boucle légèrement différente (une qui utilise
k code> tôt dans le corps de la boucle) susceptible d'empêcher OMP de faire toute parallélisation du tout. Mais peut-être que c'est le point de déclarer
k code> partagé, je ne sais pas ...
@Stevejessop: Oui, c'est ce que je soulignais ... qu'il pourrait y avoir une fonctionnalité plus complexe cachée derrière elle lorsque nous exprimons explicitement que k code> est partagé entre les threads. Cependant j'ai édité ma réponse :)
la bonne façon de capturer et d'incrémenter K
@Msalters: c'est un lien impressionnant :)
La réponse simple est que Pour ce faire en toute sécurité en parallèle, vous devez synchroniser afin de vous assurer que Synchronisation en C ++ 11 peut facilement être obtenu en utilisant un std :: vecteur :: push_back code> n'est pas thread-coffre-fort. p>
push_back code> n'est pas appelé à partir de plusieurs threads en même temps. P>
std :: mutex code>. p>
Pourquoi pas seulement mettre un #pragma omp critique code> avant le push_back?
@Daviddoria Je ne connais pas OpenMP et j'ai simplement donné la solution standard C ++.
@Daviddoria Votre suggestion a parfaitement fonctionné pour moi. Vous devriez en faire une réponse officielle
@Vinf. Je viens de poster la recommandation "critique" comme réponse.
Vous pouvez essayer d'utiliser un mutex pour résoudre le problème.
Habituellement, je préfère réaliser une telle chose moi-même; espère que cela pourrait aider. P> P>
Bonne démonstration de la raison pour laquelle vous ne devriez pas essayer d'écrire votre propre mutex
L'utilisation d'un mutex pour synchroniser les accès au vecteur est une approche plausible, mais la seule chose que votre code vous synchronise la température de la CPU avec le temps que votre programme est exécuté.
Utilisez le vecteur simultané Il s'agit de la version sécurisée de fil Vecteur. p> p> Concurrence :: Concurrent_vector
Je ne vois pas aucune preuve i> n'importe où que concurrent_vector code> est "en C ++ 11". Il y en a une implémentation dans les blocs de construction de threading d'Intel comme
TBB: Concurrent_vector Code >
et l'exécution de la concurrence de Microsoft (conclure) a AA Concurrence :: Concurrent_vector code>
, mais ceux-ci sont spécifiques à Intel TBB et Visual C ++, respectivement. (OpenMP peut utiliser i> être utilisé dans MSVC, accordé. Mais Intel recommande de ne pas le mélanger avec TBB.)
mettre un #pragma omp critique code> avant le
push_back code>. p>
J'ai résolu un problème similaire en dérivant la classe Voici mon implémentation de vecteur "openmp-coffre-fort": p> Bien sûr, vous devez inclure si vous avez toujours besoin de la sortie code> de la sortie code> ailleurs dans une section non parallèle du code, Vous pouvez simplement utiliser la méthode normale std :: vecteur code> classement pour implémenter un
atomic_push_back code> méthode, approprié pour fonctionner dans le
openmp code > Paradigm.
omp.h code>. Ensuite, votre code pourrait être juste comme suit: p>
push_back code>. p> p>
Utilisez-vous des mécanismes de synchronisation?
@Luchiangriggore: Non! Le code est comme indiqué ci-dessus!
Les fonctions de non-const de
std code> ne sont pas thread-coffre-fort; Vous devez synchroniser si vous souhaitez les modifier simultanément.
Vous avez de la chance que vous n'appeliez pas
sortie.Reserve (saisie.Rows) code>. Cela aurait empêché la réaffectation de la mémoire, mais le code serait toujours un danger-danger. Et cela pourrait se manifester dans des valeurs «manquantes», ce qui serait beaucoup plus difficile à repérer.
La sortie doit-elle être commandée comme l'entrée? Garder cet ordre est un peu un défi lorsque l'entrée réelle n'est pas traitée dans l'ordre et qu'il n'y a pas de correspondance de 1 à 1 avec
sortie [] code>. Selon les vitesses relatives de toutes les fonctions, il peut être utile de déterminer
Goodinput [] code> séquentiellement, puis convertissez ce 1 à 1, en parallèle, à
de sortie [] code>. Si
isgoodmatch code> est le problème, calculez
INPUTMASK [] code> en parallèle, puis faites le reste séquentiellement.
@Msalters: la sortie n'a pas besoin d'être dans le même ordre que l'entrée.
Certaines personnes, lorsqu'elles sont confrontées à un problème, pensez-moi, "je sais, je vais utiliser des threads", puis deux ils ont des efforts.