web-dev-qa-db-fra.com

Utiliser OpenMP avec Clang

J'ai des problèmes pour compiler le code OpenMP avec Clang (3.6 et 3.8 ToT).

J'ai suivi cet article de blog http://blog.llvm.org/2015/05/openmp-support_22.html , mais le problème est que le programme compilé est exécuté sur un seul thread . m utilisant ubuntu 15.04 x64, libgomp et libiopmp sont installés et je compile mon code à l’aide de la commande suivante:

clang test.c -o test -fopenmp -L/usr/lib/gcc/x86_64-linux-gnu/5.1.1

Quand j'utilise gcc à la place, tout fonctionne bien: gcc test.c -o test -fopenmp

J'ai aussi essayé de courir export LD_LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/5.1.1:$LD_LIBRARY_PATH mais ça n'a pas aidé . `

Aucune suggestion?

16
kuhar

Mettre à jour

Construire la dernière version de LLVM/Clang (clang-3.8), installer libiomp5 et spécifier l'emplacement des fichiers d'en-tête gomp omp a fonctionné. Notez que le paquet Ubuntu pour libiomp5 n'est pas tout à fait correct, vous devrez donc ajouter un lien symbolique dans/usr/lib à partir de /usr/lib/libiomp5.so à /usr/lib/libiomp5.so.5.

./clang++ -I/usr/lib/gcc/x86_64-linux-gnu/4.9/include -fopenmp=libiomp5 -o test test.cpp

J'utilise g ++ - 5.1 et clang ++ - 3.6 sur Linux Mint 17.2 (essentiellement Ubuntu trusty) et je vois les mêmes résultats avec le code suivant.

#include <iostream>
#include <omp.h>
int main() {
    #pragma omp parallel num_threads(4)
    {
        #pragma omp critical
        std::cout << "tid = " << omp_get_thread_num() << std::endl;
    }
}

L'exécution de cette sous-trace révèle le problème:

g ++

$ g++ -fopenmp -o test test.cpp
$ ./test
tid = 0
tid = 3
tid = 2
tid = 1
$ ltrace ./test
__libc_start_main(0x400af6, 1, 0x7ffc937b8198, 0x400bc0 <unfinished ...>
_ZNSt8ios_base4InitC1Ev(0x6021b1, 0xffff, 0x7ffc937b81a8, 5)   = 0
__cxa_atexit(0x4009f0, 0x6021b1, 0x602090, 0x7ffc937b7f70)     = 0
GOMP_parallel(0x400b6d, 0, 4, 0 <unfinished ...>
GOMP_critical_start(0, 128, 0, 0)                              = 0
tid = 3
tid = 2
omp_get_thread_num(0x7f9fe13894a8, 1, 0, 0x493e0)              = 0
_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc(0x6020a0, 0x400c44, 0, 0x493e0) = 0x6020a0
_ZNSolsEi(0x6020a0, 0, 0x7f9fe1a03988, 0x203d2064)             = 0x6020a0
_ZNSolsEPFRSoS_E(0x6020a0, 0x400920, 0x7f9fe1a03988, 0 <unfinished ...>
_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_(0x6020a0, 0x400920, 0x7f9fe1a03988, 0) = 0x6020a0
<... _ZNSolsEPFRSoS_E resumed> )                               = 0x6020a0
GOMP_critical_end(0x7f9fe0d2d400, 0x7f9fe0d2e9e0, 0, -1)       = 0
tid = 1
tid = 0
<... GOMP_parallel resumed> )                                  = 0
_ZNSt8ios_base4InitD1Ev(0x6021b1, 0, 224, 0x7f9fe0d2df50)      = 0x7f9fe1a08940
+++ exited (status 0) +++

bruit

$ clang++ -fopenmp -o test test.cpp
$ ./test
tid = 0
$ ltrace ./test
__libc_start_main(0x4009a0, 1, 0x7ffde4782538, 0x400a00 <unfinished ...>
_ZNSt8ios_base4InitC1Ev(0x6013f4, 0x7ffde4782538, 0x7ffde4782548, 5) = 0
__cxa_atexit(0x400830, 0x6013f4, 0x6012c8, 0x7ffde4782310)     = 0
_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc(0x6012e0, 0x400a84, 0x7ffde4782548, 6) = 0x6012e0
omp_get_thread_num(0x7f3e4698c006, 0x7f3e4698c000, 0x7f3e46764988, 1024) = 0
_ZNSolsEi(0x6012e0, 0, 0x7f3e46764988, 1024)                   = 0x6012e0
_ZNSolsEPFRSoS_E(0x6012e0, 0x4007a0, 0x7f3e46764988, 0 <unfinished ...>
_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_(0x6012e0, 0x4007a0, 0x7f3e46764988, 0) = 0x6012e0
tid = 0
<... _ZNSolsEPFRSoS_E resumed> )                               = 0x6012e0
_ZNSt8ios_base4InitD1Ev(0x6013f4, 0, 224, 0x7f3e45886f50)      = 0x7f3e46769940
+++ exited (status 0) +++

Vous pouvez immédiatement voir le problème: clang ++ n’appelle jamais GOMP_parallel, vous obtenez donc toujours un thread. C'est un comportement fou de la part de Clang. Avez-vous essayé de construire et d’utiliser la "spéciale" Version OpenMP of clang?

8
Tim

Quelques commentaires supplémentaires:

1) Vous devez utiliser -fopenmp = libomp pour activer OpenMP dans Clang. -fopenmp lie simplement libgomp mais ignore tous les pragmas. Bizarre, je sais - et sera bientôt changé dans le coffre.

2) 3.7 est la première version prenant en charge OpenMP. 3.6 pas.

3) Clang est seulement capable de travailler avec libomp. Ne mettez pas libgomp (en-têtes ou la bibliothèque) dans le chemin de libomp! Clang utilise l'API Intel, non prise en charge par libgomp. -fopenmp = libomp doit lier la bonne bibliothèque.

Le tiens,

Andrey Bokhanko

Ingénieur logicielIntel

14
Andrey Bokhanko

Je l'ai fait fonctionner sur Linux Mint 17.2. (essentiellement Ubuntu 14.04) avec:

les paquets: libiomp-dev clang-3.8

Drapeau de compilation: -fopenmp

Drapeau de l'éditeur de liens: -fopenmp=libiomp5

Maintenant, il compile et utilise plusieurs threads.

Voici le modifié FindOpenMP.cmake

6
veio

La variable d’environnement OMP_NUM_THREADS est probablement ce que vous voulez. Vous pouvez également le définir par programme.

https://gcc.gnu.org/onlinedocs/libgomp/Environment-Variables.html

Et pareil pour Clang.

0
Jack Wasey