81 votes

Pourquoi l'opérateur! = N'est-il pas autorisé avec OpenMP?

J'ai essayé de compilé le code suivant:

#pragma omp parallel shared (j)
{
   #pragma omp for schedule(dynamic)
   for(i = 0; i != j; i++)
   {
    // do something
   }
}

J'ai cette erreur: erreur: invalid contrôle de prédicat.

J'ai vérifier le openMP guide de référence et il est dit que pour le parallèle pour "seulement" permet à l'un des opérateurs suivants: < <= > >=.

Je ne comprends pas pourquoi ne pas autoriser i != j. Je pourrais comprendre si c'était la statique de l'horaire, puisque openMP besoin de pré-calculer le nombre d'itérations affecté à chaque thread. Mais je ne comprends pas pourquoi cette limitation dans de tels cas, par exemple. Des indices ?


EDIT: même si je le fais, for(i = 0; i != 100; i++), bien que je pourrais juste mettre "<" ou "<=" .

82voto

dreamcrash Points 8227

.

J'ai envoyer un e-mail à l'OpenMP les développeurs sur ce sujet, la réponse :

Pour la signature de l'int, l'écharpe autour de comportement est indéfini. Si nous le permettent !=, les programmeurs peuvent obtenir inattendu tripcount. Le problème est de savoir si le compilateur peut générer du code pour le calcul d'un voyage de comptage de la boucle.

Pour une simple boucle, comme:

for( i = 0; i < n; ++i )

le compilateur peut déterminer qu'il existe des 'n' itérations, si n>=0, et zéro itérations si n < 0.

Pour une boucle comme:

for( i = 0; i != n; ++i ) 

encore une fois, un compilateur doit être en mesure de déterminer qu'il existe des 'n' itérations, si n >= 0; si n < 0, nous ne savons pas combien d'itérations.

Pour une boucle comme:

for( i = 0; i < n; i += 2 )

le compilateur peut générer du code pour calculer le voyage count (nombre d'itérations de la boucle) floor((n+1)/2) si n >= 0, et 0 si n < 0.

Pour une boucle comme:

for( i = 0; i != n; i += 2 )

le compilateur ne peut pas déterminer si " je " ne sera jamais hit 'n'. Si " n " est un nombre impair?

Pour une boucle comme:

for( i = 0; i < n; i += k )

le compilateur peut générer du code pour calculer le voyage comte de floor((n+k-1)/k) si n >= 0, et 0 si n < 0, car le compilateur sait que la boucle doit compter jusqu'; dans ce cas, si k < 0, c'est pas un programme OpenMP.

Pour une boucle comme:

for( i = 0; i != n; i += k )

le compilateur ne sait même pas si je compte vers le haut ou vers le bas. Il ne sait pas si " je " ne sera jamais hit 'n'. Il peut être une boucle infinie.

Credites: OpenMP CEA

19voto

Hristo Iliev Points 29262

Contrairement à ce à quoi il pourrait ressembler, schedule(dynamic) ne fonctionne pas avec la dynamique d'un nombre d'éléments. Plutôt la cession de l'itération des blocs de threads est ce qui est dynamique. Avec ordonnancement statique, cette cession est précalculée au début du partage des tâches de construction. Avec la dynamique de la planification d'itération blocs sont donnés aux discussions sur le premier venu, premier servi.

Le standard OpenMP est assez clair que le montant de iteratons est précalculée une fois le workshare construire est rencontrés, d'où le compteur de la boucle ne peut pas être modifié à l'intérieur du corps de la boucle (OpenMP 3.1 spécification, §2.5.1 - Boucle de Construire):

Le nombre d'itérations pour chaque boucle associé est calculé avant l'entrée à l'extérieur de la boucle. Si l'exécution de tout associé de la boucle de changer les valeurs utilisées pour calculer tout de l'itération compte, alors le comportement est indéterminé.

Le type entier (ou en nature, pour Fortran) est utilisée pour calculer le nombre d'itérations pour la s'est effondré boucle est définie par l'implémentation.

Un partage des tâches boucle est logique itérations numérotés 0,1,...,N-1 où N est le nombre de itérations de boucle, et la logique de numérotation indique l'ordre dans lequel les itérations serait exécuté si la boucle associé(s) ont été exécutées par un seul thread. L' schedule clause spécifie combien d'itérations des boucles sont divisés en contiguë non vide de sous-ensembles, appelés segments, et comment ces morceaux sont distribués parmi les fils de l'équipe. Chaque thread exécute son morceau(s) dans le contexte de sa tâche implicite. Le chunk_size expression est évaluée à l'aide de la liste originale des éléments de toutes les variables qui sont privé dans la boucle de construire. Il n'est pas précisé si, dans quel ordre, ou combien de fois, tous les effets secondaires de l'évaluation de cette expression se produire. L'utilisation d'une variable dans une schedule clause expression d'une boucle de construire provoque une référence implicite à la variable dans tous les enfermant des constructions.

Le raisonnement derrière ces relationnelle de l'opérateur de restriction est très simple - il fournit une indication claire sur ce qu'est le sens de la boucle, il s'installe facilement le calcul du nombre d'itérations, et il offre la même sémantique de la OpenMP le partage du travail directive en C/C++ et Fortran. Aussi d'autres opérations relationnelles impose d'inspection du corps de la boucle afin de comprendre comment la boucle est qui serait unaceptable dans de nombreux cas, et ne permettrait pas la mise en œuvre de la lourdeur.

OpenMP 3.0 a introduit l'explicite task construction qui permet pour la parallélisation des boucles avec inconnu nombre d'itérations. Il ya un hic cependant: les tâches de présenter certains graves, les frais généraux et la une tâche par itération de boucle n'a de sens que si ces itérations prendre un certain temps à être exécutées. Sinon, les frais généraux de dominer le temps d'exécution.

7voto

Jonathan Dursi Points 25143

Il y a un million d'équivalent sur le plan fonctionnel des choses qui pourrait en principe être admis:

for (int i=0; (i-j)!=0; i++) 
    ....

ou

for (int i=0, k=j; (i!=j)&&(k!=0); i++, k--)

ou

for (int i=0; i-j < 1 && j-i < 1; i++)
    ....

ou

inline int f(int i, int j) {
    return (i != j);
}

..

for (int i=0; f(i,j); i++) 
        ....

Mais finalement, le compilateur écrivains ont à mettre en œuvre des directives OpenMP qui doit prendre en charge, entre autres choses, efficace statique de la décomposition de la boucle entre les processeurs, avec une quantité limitée de ressources. Le standard est le document qui essaie d'établir un équilibre entre la flexibilité et la facilité d'utilisation pour les développeurs d'une part, et la traçabilité pour les exécutants.

Vous pourriez certainement essayer de donner de la rétroaction à la commission; je ne peux pas imaginer ce cas particulier pourrait être particulièrement difficile pour les réalisateurs. D'autre part, je ne vois pas que la notation particulière pour une boucle de tous que, souvent, je ne sais donc pas quelle est la priorité accordée il serait; il n'est pas comme demander aux développeurs de modifier un != d'un < ou > est une énorme imposture.

5voto

bobcgausa Points 41

La réponse est simple OpenMP ne permet pas de terminer prématurément une équipe de threads. Avec == ou! =, OpenMP n’a aucun moyen de déterminer quand la boucle s’arrête. 1. Un ou plusieurs threads peuvent rencontrer la condition de terminaison, qui peut ne pas être unique. 2. OpenMP n'a aucun moyen de fermer les autres threads qui pourraient ne jamais détecter la condition.

2voto

Richard Points 5991

Si je devais le voir la déclaration de

for(i = 0; i != j; i++)

utilisé à la place de la déclaration

for(i = 0; i < j; i++)

Je serais vous demandez-vous pourquoi le programmeur a fait le bon choix, jamais l'esprit qu'il peut dire la même chose. Il se peut que OpenMP est de faire un dur choix syntaxiques afin de forcer une certaine clarté du code.

Voici le code qui pose des défis pour l'utilisation de l' != et peut aider à expliquer pourquoi il n'est pas autorisé.

#include <cstdio>

int main(){
    int j=10;
   #pragma omp parallel for
   for(int i = 0; i < j; i++){
    printf("%d\n",i++);
   }
}

notez que i est incrémenté à la fois l' for déclaration ainsi que dans la boucle elle-même, conduisant à la possibilité (mais pas de la garantie) d'une boucle infinie.

Si le prédicat est - < puis la boucle du comportement peut être encore bien défini dans un contexte parallèle sans le compilateur avoir à vérifier à l'intérieur de la boucle pour des changements à l' i , et à déterminer comment ces changements affecteront la boucle de limites.

Si le prédicat est - != puis la boucle du comportement n'est plus bien défini, et il peut être infinie dans la mesure, la prévention de facile en parallèle de la subdivision.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X