2010-08-26 6 views
27

Ho un'estensione C in cui mi piacerebbe utilizzare OpenMP. Quando importo il mio modulo, però, ottengo un errore di importazione:Estensioni Python e OpenMP C


ImportError: /home/.../_entropysplit.so: undefined symbol: GOMP_parallel_end 

ho compilato il modulo con -fopenmp e -lgomp. Questo perché la mia installazione di Python non è stata compilata con il flag -fopenmp? Dovrò creare Python dal sorgente? O c'è qualche altra possibilità? Questa è l'unica volta che in realtà uso OpenMP nel mio modulo:


unsigned int feature_index; 
#pragma omp parallel for 
for (feature_index = 0; feature_index < num_features; feature_index++) { 

mi piacerebbe attaccare con OpenMP se è possibile, proprio perché è così facile e la parallelizzazione in questo caso si adatta bene.

EDIT: ho morso il proiettile e ho ricompilato Python con il supporto OpenMP. Il mio modulo funziona perfettamente ora, ma questa non è davvero una grande soluzione. Non posso davvero distribuirlo se richiede una ricompilazione completa di Python. Quindi qualcuno sa in qualche modo intorno a questo? Funzionerebbero i ctypes, forse?

RISOLTO! Era un semplice problema di collegamento. (Ho ricostruito Python per quello ?!) OpenMP non era collegato correttamente durante la compilazione del modulo. Quindi è IS possibile caricare un'estensione Python C che utilizza OpenMP.

+0

Si potrebbe considerare di copiare la soluzione in una risposta "reale" pubblicata sotto questa domanda, in modo che sia più semplice da vedere (e possa essere messo in vendita). –

+0

Grazie, lo farò. – ajduff574

risposta

16

solo per rendere più chiaro, qui è ciò che il tuo setup.py dovrebbe essere simile:

ext = Extension(
     'milk.unsupervised._som', 
     sources = ['milk/unsupervised/_som.cpp'], 
     extra_compile_args=['-fopenmp'], 
     extra_link_args=['-lgomp']) 


... 
setup(..., ext_modules = [ext]) 
+1

Ora, come farlo in un modo multipiattaforma che funziona con le versioni di gcc, msvc e Clang che supportano diversamente l'openmp e il fallback? –

+0

@ColonelPanic: Mi piacerebbe anche saperlo. – luispedro

3

Si è trattato di un semplice problema di collegamento. OpenMP non era collegato correttamente durante la compilazione del modulo. Quindi è possibile caricare un'estensione Python C che utilizza OpenMP. -fopenmp deve essere passato al compilatore e -lgomp al linker - se stai usando distutils, assicurati che setup.py sia configurato correttamente. Anche la ricostruzione di Python ha funzionato, suppongo, perché avevo collegato correttamente OpenMP con Python, quindi quando Python ha caricato il modulo la libreria era già correttamente collegata.

6

So che questo è un post datato, ma io condividere la mia esperienza come troppo mi sono imbattuto in questo esatto stesso problema, ma quando si utilizza f2py nella riga di comando. Mi è stato originariamente la compilazione mio OpenMP abilitato Fortran 90 subroutine utilizzando

f2py --fcompiler=gfortran --f90flags='-fopenmp -lgomp' -m sub -c sub.90 

che con successo ha creato l'oggetto condiviso sub.so. Tuttavia, il tentativo di importarlo da una shell Python ha prodotto il simbolo simile non definito ImportError. Comunque, come ha affermato l'autore originale, stavo cercando di passare sia -fopenmp che -lgomp al compilatore , mentre solo -fopenmp dovrebbe essere passato ad esso, e -lgomp dovrebbe essere passato al linker.

Pertanto, avrei fatto la seguente

f2py --fcompiler=gfortran --f90flags='-fopenmp' -lgomp -m sub -c sub.f90 

E questo è tutto, problema risolto, ora posso importare il mio subroutine.