【问题标题】:Python runtime: recompiling and reusing C libraryPython 运行时:重新编译和重用 C 库
【发布时间】:2011-07-17 06:46:12
【问题描述】:

我正在开发一种工具,用于对用户定义的函数进行一些数值分析。 这个想法是在 Python 中制作一个方便的 UI,用户可以在其中输入 C 函数,然后按下一个按钮 - 并接收一些输出数据。 计算可能需要几分钟或几小时,因此仅 Numpy 的性能是不可接受的。

我尝试了以下方法:基于 Python 的 UI 调用 gcc,从用户函数编译 dll,而不是在 Cython 包装中我的基于 C 的核心算法使用。它可以工作,但是由于无法完全卸载python模块,所以我无法重新编译用户定义的函数,直到整个UI程序关闭并再次运行。

我现在看到的唯一方法是将计算核心和 UI 进程分开,然后让它们通过共享内存/消息传递进行交互。当用户想要更新他的功能时,程序终止内核,重新编译dll并再次启动内核。

您能建议在这种情况下的任何常见做法吗?

谢谢!

【问题讨论】:

    标签: python c jit scientific-computing cython


    【解决方案1】:

    Python 具有非常好的multiprocessing 支持(并且确实不是很好的线程支持),因此您可以为每个要评估的表达式生成一个新的 python 进程,在新进程中编译和加载 dll,然后让它通信结果返回父进程。当生成的进程退出时,所有内容都应该被卸载。

    【讨论】:

    • 感谢您指出多处理!我尝试使用 threading.Thread 并且加入后没有卸载库。使用 multiprocessing.Process 加入卸载 Linux 和 Windows 中的库,因此可以重新编译和重新加载它们。很可能,我会继续朝这个方向发展。
    【解决方案2】:

    每次用户输入一个函数时,您都可以生成一个具有随机、唯一名称的新模块(就像您对临时文件所做的那样)。然后编译那个模块,加载它,然后调用函数。

    随着时间的推移,这当然会导致加载大量模块。如果用户没有在单个会话中运行太多功能,您可能会侥幸成功。或者,您可以在普通 DLL 而不是 Python 模块中编译该函数,并使用 ctypes 加载它。完成 DLL 后,只需丢弃对它的任何引用——当 ctypes 句柄最终被 gced 时,它应该卸载 DLL(参见 How can I unload a DLL using ctypes in Python?)。

    您可能还想从磁盘中删除您的 DLL。如果您使用的是 Windows,这可能会很棘手,因为很难预测 ctypes 何时会卸载它,而且 Windows 不会让您删除它,因为它正在使用中。

    【讨论】:

    • 感谢您的想法。我找到了“如何在 Python 中使用 ctypes 卸载 DLL?”前段时间的问题,并决定在这里不使用ctypes。正如我所见,没有人确定在这种“卸载”之后库实际上不再使用。
    【解决方案3】:

    您是否考虑过WeaveInstant (less up-to-date)?我自己只使用了instant,但对于您所描述的内容,似乎两者都完美

    它们都可以在运行时从字符串中自动编译和缓存 c 代码。我只使用instant 来内联c,但我确信它或weave 在编译用户输入时同样适用。

    这是一个如何使用编织的示例,来自tutorial

    >>> a = 'string'
    >>> def protected_printf(a):
    ...     assert(type(a) == type(1))
    ...     weave.inline(r'printf("%d\n",a);',['a'])
    >>> protected_printf(1)
     1
    >>> protected_printf('string')
    AssertError...
    

    【讨论】:

    • 据我了解,Weave 不是解决方案,因为我希望从我的预编译 C 库中调用用户定义的函数。整个调用链是:Python GUI->Cython 接口模块(编译.so)->C 计算核心(编译.so)->userfunc.so。并且只有最后一个库要在 Python 运行时编译。
    • 好吧,我猜不是。我把这个留在这里作为对其他旅行者的警告。
    猜你喜欢
    • 1970-01-01
    • 2010-11-24
    • 1970-01-01
    • 2017-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多