在 python 的 c 扩展中包括外部共享英特尔的 mkl 库
Including external shared intel's mkl library in c extension for python
我写了一个 python c 扩展,它使用来自 Intel 的数学内核库 (mkl) 的例程。这是我第一次写c扩展。我今天才知道。
已编译的c扩展。但是当我在 python 中导入它时,它说未定义的符号,并且找不到在 mkl.
中定义的函数
如何在 python c 扩展中包含任何外部 c 库?
感谢您的帮助。
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:
import mkl_helper
运行test.py的结果:
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 表示,如果 link 作为共享库,即使在另一个 C 扩展中包含一个 C 扩展也会出现问题。所以,我想我必须 link 将 mkl 作为静态库?或将 inlcude mkl.h 添加到 python.h?
但是,在 python(没有 c)中,我可以使用 ctypes.cdll.LoadLibrary("./mkl_rt.so") 加载 mkl 的共享库,然后使用 c 函数共享库没有问题(如)。然而 Python/C api 不能在 c 中做同样的事情吗?
对于 link 静态外部 c 库,setup.py 可能需要:
在 https://docs.python.org/2/distutils/apiref.html?highlight=include#distutils.ccompiler.CCompiler.add_include_dir
class distutils.core.Extensions 中的额外对象
关于cython的相关问题没有答案:Combining Cython with MKL
这个似乎更有帮助:Python, ImportError: undefined symbol: g_utf8_skip
这个使用已弃用的 dlopen:Undefined Symbol in C++ When Loading a Python Shared Library
oopcode 在 Python, ImportError: undefined symbol: g_utf8_skip 中的回答有效。
情况有所改善。
导入c扩展到python没有错误。
从 python 调用 c 扩展会出现以下错误:
英特尔 MKL 致命错误:无法加载 libmkl_mc.so 或 libmkl_def.so。
我记得当我用 mkl 手动编译 numpy 时,site.cfg 文件要求提供库路径和包含英特尔 mkl 的路径。我想我也需要将库路径添加到 extra_link_args 中……但这没有用。
使用 anaconda 的人也有 here 中的错误。
英特尔论坛上的类似案例 here.
这个 Whosebug 问题说 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 仍然只使用 12 cpu.
中的一个
我写了一个 python c 扩展,它使用来自 Intel 的数学内核库 (mkl) 的例程。这是我第一次写c扩展。我今天才知道。
已编译的c扩展。但是当我在 python 中导入它时,它说未定义的符号,并且找不到在 mkl.
中定义的函数如何在 python c 扩展中包含任何外部 c 库?
感谢您的帮助。
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:
import mkl_helper
运行test.py的结果:
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 表示,如果 link 作为共享库,即使在另一个 C 扩展中包含一个 C 扩展也会出现问题。所以,我想我必须 link 将 mkl 作为静态库?或将 inlcude mkl.h 添加到 python.h?
但是,在 python(没有 c)中,我可以使用 ctypes.cdll.LoadLibrary("./mkl_rt.so") 加载 mkl 的共享库,然后使用 c 函数共享库没有问题(如
对于 link 静态外部 c 库,setup.py 可能需要: 在 https://docs.python.org/2/distutils/apiref.html?highlight=include#distutils.ccompiler.CCompiler.add_include_dir
class distutils.core.Extensions 中的额外对象关于cython的相关问题没有答案:Combining Cython with MKL
这个似乎更有帮助:Python, ImportError: undefined symbol: g_utf8_skip
这个使用已弃用的 dlopen:Undefined Symbol in C++ When Loading a Python Shared Library
oopcode 在 Python, ImportError: undefined symbol: g_utf8_skip 中的回答有效。 情况有所改善。
导入c扩展到python没有错误。 从 python 调用 c 扩展会出现以下错误: 英特尔 MKL 致命错误:无法加载 libmkl_mc.so 或 libmkl_def.so。
我记得当我用 mkl 手动编译 numpy 时,site.cfg 文件要求提供库路径和包含英特尔 mkl 的路径。我想我也需要将库路径添加到 extra_link_args 中……但这没有用。
使用 anaconda 的人也有 here 中的错误。 英特尔论坛上的类似案例 here.
这个 Whosebug 问题说 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 仍然只使用 12 cpu.
中的一个