2013-04-15 7 views
1

Je commence juste à utiliser OpenMP et j'écris une fonction qui divise un tableau en numBlocks blocs et calcule un histogramme sur chaque bloc (ie, un histogramme par bloc) en inspectant les éléments blockSize de chaque bloc (dans le code que je fournis, l'histogramme enregistre la divisibilité des éléments dans le bloc par les entiers 1 à numBuckets).Différence entre deux boucles omp

Dans la première je créer boucle omp for un fil pour chaque bloc en utilisant:

#pragma omp for schedule(static) 
for(uint blockNum = 0; blockNum < numBlocks; blockNum++){ 
    for(uint blockSubIdx = 0; blockSubIdx < blockSize; blockSubIdx++){ 
     uint idx = blockNum * blockSize + blockSubIdx; 
     // Compute histogram here by examining array[idx] 
    } 
} 

il mise en œuvre d'une autre manière, je vous prie fils de chaque opérer sur blockSize éléments, où je l'ai déjà affirmé que array.size() == numBlocks * blockSize:

#pragma omp for schedule(static, blockSize) 
for(uint idx = 0; idx < array.size(); idx++){ 
    uint blockNum = idx/blockSize; 
    // Compute histogram here by examining array[idx] 
} 

Cette deuxième méthode ne fonctionne pas correctement si j'augmente le nombre de threads (en utilisant export OMP_NUM_THREADS) au-dessus d'un certain seuil (78 sur mon nœud de calcul) - le résultat h Les valeurs de l'istogramme ne correspondent pas à celles d'un calcul en série.

Selon https://computing.llnl.gov/tutorials/openMP/, il semble que les blocs de taille blockSize dans la deuxième méthode sont contigus, donc je ne comprends pas pourquoi il échoue. Cependant, il semble que plusieurs threads écrivent sur le même index dans l'histogramme. Y a-t-il une subtilité qui me manque?

Voici un aperçu de l'ensemble du code source: https://gist.github.com/anonymous/5391777.

MISE À JOUR: Le seuil de fil ne montre une certaine dépendance à l'égard array.size(). Ce n'est pas la valeur particulière du seuil que j'essaie de comprendre, mais plutôt l'existence du seuil.

Répondre

2

Il me semble que vous essayez de fusionner la boucle. Tu pourrais essayer ça. Je ne sais pas si cela répond à votre question.

#pragma omp parallel for schedule(static) 
for(uint n = 0; n < (numBlocks*blockSize); n++){ 
    uint blockNum = n/blockSize; 
    uint blockSubIdx = n%blockSize; 
    uint idx = blockNum * blockSize + blockSubIdx; 
    // Compute histogram here by examining array[idx] 
} 

Aussi, pourquoi essayez-vous d'augmenter le nombre de threads? Votre UC ne peut exécuter qu'un certain nombre de threads matériels en même temps. Augmenter le nombre de threads pour OpenMP ne va pas aider les performances. Pourquoi ne pas les laisser à la valeur par défaut?

Enfin, si le calcul de l'histogramme prend un temps différent en fonction de idx, vous pouvez essayer schedule(dynamic) à la place.

+0

Cet extrait de code présente le même bogue que mon second extrait de code (l'histogramme calculé est corrompu). En fait, puisque 'schedule' n'est pas passé' blockSize' pour son second argument, je m'attendrais à ce que l'histogramme calculé soit corrompu (plusieurs threads mettraient à jour le nombre d'histogrammes pour le même bloc). J'ai essayé d'augmenter le nombre de threads parce que je veux voir la performance se dégrader quand il y a plus d'un thread par CPU, juste pour montrer que ça se passe réellement. – DMack

+0

Je viens d'exécuter votre code par défaut. Ça fonctionne bien pour moi. Je ne sais pas ce que vous voulez dire par nombre de threads élevé. Changez-vous omp_set_num_thread (n)? Je ne vois ça nulle part dans votre code. Je ne vois pas de bogue. Le code que j'ai énuméré ci-dessus devrait fonctionner correctement. C'est une façon standard de fusionner une boucle tant que vous utilisez idx tel que défini. –

+0

Avant d'exécuter le code, j'ai défini la variable d'environnement OMP_NUM_THREADS (comme mentionné dans mon article). Je suppose que cela aurait été plus clair si j'utilisais omp_set_num_threads() dans mon code à la place. Quand je l'ai placé trop haut (au-dessus de 78 sur mon noeud de calcul), le code ne fonctionne pas (l'histogramme calculé est corrompu). Essentiellement, ma question est de savoir pourquoi la boucle fusionnée présente ce comportement dépendant du nombre de threads. – DMack