在iPython笔记本中我试图使用笔记本功能%%cython_pyximport
编写一个cython函数,我稍后可以在笔记本中调用它。
我想使用此命令而不是%%cython
,因为它似乎有相当多的开销。例如,当我描述我的代码时,我得到了这个:
168495 function calls in 4.606 seconds
Ordered by: internal time
ncalls tottime percall cumtime percall filename:lineno(function)
1 3.234 3.234 4.605 4.605 {_cython_magic_0ef63e1ad591c89b73223c7a86d78802.knn_alg}
11397 0.326 0.000 0.326 0.000 {method 'reduce' of 'numpy.ufunc' objects}
987 0.152 0.000 0.266 0.000 decomp.py:92(eig)
987 0.118 0.000 0.138 0.000 function_base.py:3112(delete)
我希望使用%%cython_pyximport
会减少调用此函数所花费的时间。如果有更好的方法,请告诉我。
所以回到我的实际问题 - 当我使用%%cython_pyximport
时,我收到此错误:
ImportError: Building module function failed: ['DistutilsPlatformError: Unable to find vcvarsall.bat\n']
也许这与我的PATH上没有的东西有关,但我不确定。我该怎么做才能解决这个问题?
我正在使用Windows 7,Python 2.7.6(与Anaconda一起安装),Cython 0.20.1,iPython Notebook 2.1.0
编辑: 所以在按照@IanH的建议后,我现在有了这个错误:
fatal error: numpy/arrayobject.h: No such file or directory
似乎需要包含额外的头文件,以便numpy与pyximport一起使用。在这个页面上https://github.com/cython/cython/wiki/InstallingOnWindows
提到了这个错误以及如何解决它,但我对如何应用这个错误感到迷失,以便%% cython_pyximport命令在我的笔记本中起作用。
答案 0 :(得分:1)
这里有两个不同的问题。 我首先要解决你似乎关心的问题。
使用pyximport而不是cython magic函数根本不应该提高速度。 鉴于您的分析结果,似乎这里的真正问题是您在循环内部调用NumPy函数。 在Cython中,你必须跟踪哪些函数调用是在C中完成的,哪些是在Python中完成的。 Numpy通用函数是Python函数,它们需要调用Python函数的成本。
您希望如何解决这个问题完全取决于您的工作。 如果你可以使用NumPy操作巧妙地将循环向量化,这可能是最好的方法,但并非所有问题都可以通过这种方式轻松解决。 有一些方法可以从Cython中调用LAPACK例程,如this answer中所述。 如果你正在进行更简单的操作(比如沿轴的求和等),你可以编写一个函数,它使用cython memoryviews在你的Cython模块内部传递切片。 在blog post中有关于正确方法的讨论。 在Cython中进行这些操作通常会有点困难,但它仍然是一个非常平易近人的问题。
现在,尽管我并不相信pyximport会实际按照您的意愿行事,但我仍然会告诉您如何让它发挥作用。
当distutils尝试使用Visual Studio编译器时,即使您没有为其设置所有内容,也会发生错误。
Anaconda默认使用MinGW进行Cython扩展,但由于某些原因,它没有设置为使用MinGW和pyximport。
虽然这很容易解决。
在您的Python安装目录中(可能是C:\Anaconda
或这些行中的某些内容),应该有一个文件Anaconda\Lib\distutils\distutils.cfg
。 (如果它不存在则创建它。)
修改它以使其内容包含以下两个选项:
[build]
compiler=mingw32
[build_ext]
compiler = mingw32
如果我没记错的话,第一个已经包含在Anaconda中了。 在撰写本文时,第二个不是。 你需要它来使pyximport工作。
答案 1 :(得分:0)
由于我安装了VS2015,不得不添加新的环境变量
SET VS90COMNTOOLS=%VS140COMNTOOLS%
答案 2 :(得分:0)
我遇到了同样的问题,所以我的解决方案是使用:
[构建] 编译器的mingw32 =
[build_ext] compiler = mingw32
在IanH的回答中,我选择直接调用gcc和cython。 我想我实际上只是绕过所有可能的错误
首先,您需要使用以下命令编译cython:
cython_commands = ['cython', '-a', '-l', '-p', '-o', c_file_name, file_path]
cython_feedback = subprocess.call(cython_commands)
然后你需要获取.c文件并通过告诉编译器在哪里查找python库来编译它。
gcc_commands = ['gcc', '-shared', '-Wall', '-O3', '-I', py_include_dir, '-L', py_libs_dir, '-o', output_name,
c_file_name, '-l', a_lib]
gcc_error = subprocess.call(gcc_commands)
py_include_dir:python安装目录的路径,标记为“include”
py_libs_dir:python安装目录的路径标记为'libs'
c_file_name:您希望中间人c文件的路径
a_lib:python安装的名称(例如'python34'或'python35'或'python27')