2016-06-16 21 views
1

私はIntelの数学カーネルライブラリ(mkl)のルーチンを使用するpython c拡張を書きました。これは、私がc拡張を書くのは初めてです。私はちょうど今日それを学んだ。Python用のcエクステンションに外部共有intelのmklライブラリを含む

コンパイルされたc拡張子。しかし、Pythonでインポートすると、未定義のシンボルが表示され、mklで定義されている関数を見つけることができません。

外部CライブラリをPythonの拡張子に含めるにはどうすればいいですか?

ありがとうございました。

mkl_helper.c:

#include "Python.h" 
#include "numpy/arrayobject.h" 
#include "mkl.h" 

static PyObject* test4 (PyObject *self, PyObject *args) 
{ 
    // test4 (m, n, 
    //  a, ja, ia, 
    //  c, jc, ic) 

    PyArrayObject *shape_array; 
    PyArrayObject *a_array; // csr_matrix.data 
    PyArrayObject *ja_array; // csr_matrix.indices 
    PyArrayObject *ia_array; // csr_matrix.indptr 
    PyArrayObject *c_array; 
    PyArrayObject *jc_array; 
    PyArrayObject *ic_array; 

    if (!PyArg_ParseTuple(args, "O!O!O!O!O!O!O!", 
          &PyArray_Type, &shape_array, 
          &PyArray_Type, &a_array, 
          &PyArray_Type, &ja_array, 
          &PyArray_Type, &ia_array, 
          &PyArray_Type, &c_array, 
          &PyArray_Type, &jc_array, 
          &PyArray_Type, &ic_array)) 
    { 
     return NULL; 
    } 

    long * ptr_int  = shape_array->data; 
    int m    = ptr_int[0]; 
    int n    = ptr_int[1]; 
    int k    = n; 

    float * a_data_ptr = a_array->data; 
    float * ja_data_ptr = ja_array->data; 
    float * ia_data_ptr = ia_array->data; 
    float * c_data_ptr = c_array->data; 
    float * jc_data_ptr = jc_array->data; 
    float * ic_data_ptr = ic_array->data; 

    char trans = 'T'; 
    int sort = 0; 
    int nzmax = n*n; 
    int info = -3; 
    int request = 0; 

    mkl_scsrmultcsr(&trans, &request, &sort, 
     &m, &n, &k, 
     a_data_ptr, ja_data_ptr, ia_data_ptr, 
     a_data_ptr, ja_data_ptr, ia_data_ptr, 
     c_data_ptr, jc_data_ptr, ic_data_ptr, 
     &nzmax, &info); 

    return PyInt_FromLong(info); 

} 

static struct PyMethodDef methods[] = { 
    {"test4", test4, METH_VARARGS, "test2(arr1)\n take a numpy array and return its shape as a tuple"}, 
    {NULL, NULL, 0, NULL} 
}; 

PyMODINIT_FUNC 
initmkl_helper (void) 
{ 
    (void)Py_InitModule("mkl_helper", methods); 
    import_array(); 
} 

setup.py:

from distutils.core import setup, Extension 
import numpy as np 

ext_modules = [ Extension('mkl_helper', sources = ['mkl_helper.c']) ] 

setup(
     name = 'mkl_helper', 
     version = '1.0', 
     include_dirs = [np.get_include()], #Add Include path of numpy 
     ext_modules = ext_modules 
) 

test.py:実行test.pyの

import mkl_helper 

結果:

Traceback (most recent call last): 
    File "<string>", line 1, in <module> 
ImportError: /home/rxu/local/lib/python2.7/site-packages/mkl_helper.so: undefined symbol: mkl_scsrmultcsr 

アップデート2016年6月16日:

これは有用であると思わ:

1.12。 https://docs.python.org/2/extending/extending.htmlに拡張モジュールのC APIを提供すると、別のc拡張モジュールに1つのc拡張を含めても、共有ライブラリとしてリンクすると問題が発生する可能性があります。だから、私は静的ライブラリとしてmklをリンクする必要がありますね?または、inlcude mkl.hをpython.hに追加しますか?

しかし、私はctypes.cdll.LoadLibrary( "./ mkl_rt.so")を使ってmklの共有ライブラリを読み込み、問題なく共有ライブラリのc関数を使用することができます。 here)。しかし、Python/CのAPIはCで同じことをすることはできません?静的に外部のCライブラリをリンクするため、setup.pyが必要になる場合があります

:応答なしとcythonについてhttps://docs.python.org/2/distutils/apiref.html?highlight=include#distutils.ccompiler.CCompiler.add_include_dir

関連質問でクラスdistutils.core.Extensionsで 余分なオブジェクト:Combining Cython with MKL

この1つは思わより有用:廃止されましたPython, ImportError: undefined symbol: g_utf8_skip

この1つのユースのdlopen:でUndefined Symbol in C++ When Loading a Python Shared Library

答えて

1

oopcodeの答えが動作します。 状況が次のように改善されました。

c拡張子をPythonにインポートするときにエラーはありません。 Pythonからc拡張を呼び出すと、次のエラーが発生します。 Intel MKLの致命的なエラー:libmkl_mc.soまたはlibmkl_def.soをロードできません。

mklで手動でnumpyをコンパイルすると、site.cfgファイルがライブラリパスを要求され、intelのmklのパスがインクルードされていることを覚えています。 extra_link_argsにもライブラリパスを追加する必要があると思います...しかし、それはうまくいきませんでした。

アナコンダを持っている人には、hereのようなエラーもあります。 似たようなケースIntelフォーラムhere

このstackoverflowの質問はextra_compile_argsも必要とされていると言う:How to pass flag to gcc in Python setup.py script

setup.py

from distutils.core import setup, Extension 
import numpy as np 

extra_link_args=["-I", "(intel's dir)/intel/compilers_and_libraries_2016.3.210/linux/mkl/include", "-L", "(intel's dir)/intel/mkl/lib/intel64/libmkl_mc.so", "-mkl"] 
ext_modules = [ Extension('mkl_helper', sources = ['mkl_helper.c'], extra_link_args=extra_link_args) ] 


setup(
     name = 'mkl_helper', 
     version = '1.0', 
     include_dirs = [np.get_include()], #Add Include path of numpy 
     ext_modules = ext_modules 
) 

更新:私は最終的にそれがhere のように働いてしまった。しかしMKL stillllちょうどのみ12のいずれかを使用 CPU。

関連する問題