2016-06-23 1 views
0

S'il vous plaît jeter un oeil à l'extrait de code suivant à l'aide OpenMP pour la parallélisation:La mise en œuvre spinlocks à synchroniser les threads OpenMP en utilisant intrinsics compilateur

char lock = 0; 
#pragma omp parallel 
{ 
    while(!__sync_bool_compare_and_swap(&lock, 0, 1)); 
    printf("Thread: %d is working!\n", omp_get_thread_num()); 
    sleep(1); 
    printf("Thread: %d unlocks lock!\n", omp_get_thread_num()); 
    lock = 0; 
} 

Est-il possible que les discussions bloquent simultanément le verrou, même si le verrouillage est atomique avec __sync_bool_compare_and_swap? Par exemple, tous les threads n'ont-ils pas une vue cohérente de la mémoire?

+0

Alors que '__sync _ *()' est une barrière complète, 'lock = 0;' ne l'est pas. – EOF

+1

Pourquoi voudriez-vous faire ça? OpenMP est exactement conçu pour fournir des abstractions appropriées, par ex. '#pragma omp crtical' dans votre cas. De la [description de '__sync_bool_compare_and_swap'] (https://gcc.gnu.org/onlinedocs/gcc-4.4.3/gcc/Atomic-Builtins.html), je suppose fortement que les barrières de la mémoire sont utilisées pour imposer une cohérence vue de la mémoire. Mais comme remarqué par EOF, le 'lock = 0;' peut être un problème dû à la réorganisation. – Zulan

+0

Alors que je suis entièrement d'accord avec vous, je travaille actuellement avec du code que je n'ai pas écrit et dans ce code, la synchronisation est renforcée comme je l'ai présenté dans le code. Et Intel Inspector détecte les conditions de course, ce qui ne devrait pas être possible si la synchronisation fonctionne comme je le souhaite. –

Répondre

2

Si vous insistez pour le faire pas comme OpenMP:

Vous devez certainement une barrière de compilateur pour empêcher lock=0 d'être reordered at compile time.

Si vous ne ciblez que x86, une barrière de compilation suffit; Sinon, utilisez un C11 atomic_thread_fence(memory_order_release) avant le lock=0, qui est juste une barrière de compilation sur x86 mais qui émettra les instructions nécessaires sur les architectures faiblement ordonnées.

Ou faire lock un type atomique, et d'utiliser un C11 stdatomic release-magasin pour le mettre à 0.


Spinning sur un lock cmpxchg prendre la serrure est assez inefficace. Vous devriez tourner sur une charge jusqu'à ce que le verrou soit disponible, puis essayez de le prendre. par exemple. vous devriez écrire quelque chose qui compilera au code like this minimal but real asm spinlock implementation.

par exemple. utiliser une charge atomique C11 avec memory_order_acquire. Ensuite, utilisez un xchg normal, pas un cmpxchg, et vérifiez si vous avez obtenu le verrou ou si un autre thread l'a pris avant vous.