【问题标题】:Python and C++ script interactionPython与C++脚本交互
【发布时间】:2011-01-28 22:19:29
【问题描述】:

我正在尝试优化我拥有的两个脚本之间的交互。 我想到的两件事是除非您手动杀死它,否则 c++ 程序不会终止,或者在将其提供给 c++ 之前在 python 中生成所有信息。

问题说明:

脚本的作用: C++ 程序(不是我做的,我不能很好地用 C++ 编程):接受一个 7 数字数组并返回一个数字,很简单。 Python 脚本(我的,我可以在 python 中编写一点程序):生成这 7 个数字数组,将它们提供给 c++ 程序,等待答案并将其添加到列表中。然后它制作下一个数组。

理论上,这是可行的。但是,就像现在一样,它会为每次调用打开和关闭 c++ 程序。对于一个没问题的阵列,但我正在尝试升级到 25k 阵列,并在未来升级到 6+ 百万阵列。显然,每次都打开/关闭它不再可行,尤其是因为 c++ 程序首先必须加载一个 130mb 的 VCD 文件才能运行。

我自己想到的两个选项是首先在 python 中生成所有数组,然后将它们提供给 c++ 程序,然后分析所有结果。但是,我不知道如何使用 6M 数组执行此操作。然而,我得到的结果与我输入的数组的顺序相同并不重要。

我想到的第二个选项是让 c++ 程序在每次调用后都不会退出。虽然我不能用 C++ 编程,所以我不知道这是否可能,保持它“活着”,这样你就可以不时将数组输入它并得到答案。

(注意:我不能用python以外的任何东西编程,我想用python做这个项目。c++程序由于速度原因不能翻译成python。)

提前致谢,马克斯。

【问题讨论】:

  • 我感到原力大乱,仿佛数百万C++程序突然惊恐地大叫起来,突然沉默了。然后我想知道“代码在哪里?”,因为没有代码就没有真正的答案。
  • 你以什么方式提供 C++ 程序(标准输入/标准输出上的管道)或套接字?。
  • 到目前为止,我还没有一套将它提供给 c++ 的方法,我正在集思广益如何做到这一点,然后提出了这个问题。我基本上仍然需要围绕 c++ 程序编写整个“包装器”,到目前为止我只有那个和 python 数组生成器。
  • 为什么需要一个 python 脚本和一个 C++ 程序来相互传递数字?您能否更具体地描述您的问题并提出问题?
  • 你有C++程序的源码,还是只有编译好的程序?

标签: c++ python optimization interaction


【解决方案1】:

首先,为了迂腐,没有正常使用的 C++ 脚本。 C++ 最终编译为机器代码,C++ 程序被恰当地称为作为“程序”而不是“脚本”。

但要回答您的问题,您确实可以将 C++ 程序设置为保留在内存中,它会在内存中侦听连接并向您的 Python 脚本发送响应。你会想学习 Unix IPC,尤其是套接字。

另一种解决方法是将 C++ 程序的功能合并到您的 Python 脚本中,而完全忘记 C++。

【讨论】:

  • 好吧对不起,以后我把它称为程序,不再称为脚本。出于速度原因,将 c++ 程序在 python 中所做的合并是不可行的,对于预期目的而言,这将花费太长时间。但很高兴听到我可以让 c++ 程序存在于内存中。我将阅读 Unix IPC 和套接字,谢谢。
  • 没什么好遗憾的!只是如果你使用正确的术语,你会更快地得到答案。有时,无论如何!
【解决方案2】:

没有源代码或Python 脚本和C++ 程序的确切规范,很难提供更多信息,但您可以反复修改C++代码从标准输入读取数组,然后将结果写入标准输出。

然后您可以使用Python subprocess module 从您的 Python 脚本启动 C++ 程序并与之通信。

请注意,简单地围绕 C++ 程序的 main() 函数进行循环不会很有帮助,因为显然主要问题是程序读取其数据所需的时间(您提到的 VCD)。

循环需要严格围绕计算结果的代码 - 这意味着您可能必须以一种允许重复完成结果计算而不会污染下一个运行的方式来考虑其他所有内容。

【讨论】:

  • 程序本身其实非常简单。它只是一个巨大的查找表(VCD),带有一个简单的函数,它接受数组并从 VCD 中返回值。所以我只需要“循环”一个给我返回值的函数?这似乎很容易。
  • @Max:只要你从stdin读取,在每次循环迭代中写入stdout并且循环外没有任何修改,应该没问题。
【解决方案3】:

好的,您最好的做法可能是为 Python 编写一个 C/C++ 扩展,该扩展能够调用 C++ 代码来执行您想要的计算。这并不是非常困难,它只需要最少量的 C/C++ 编码即可使其工作。可以在 Python 页面http://docs.python.org/extending/extending.html

上找到关于扩展 Python 的一个很好的解释

您实际上所做的是将您的 C++ 程序更改为 Python 进程可以链接并从 Python 脚本调用的动态库。

如果您需要一些帮助以使其正常工作,我相信我们可以为您提供帮助。

【讨论】:

    【解决方案4】:

    我认为最好的方法是为 python 构建 C++ 扩展模块。
    有很多方法可以做到这一点。
    如果你有 c++ 源代码,你可以试试SWIG 之后,您可以直接在 python 中使用 c++ 函数/对象 - 并通过 python 模块管理它们(此处为处理)。真的很简单。

    【讨论】:

    • 假设我的 c++ 程序只做两件事,加载 VCD 文件并在其中包含一些功能。如果我理解正确,使用 SWIG 可以让我在 python 中执行“导入 c++ 程序”,然后让我在 python 中调用该函数,对吗?这似乎是最简单的方法。但是有两个问题,这是否保留了 c++ 函数的速度,所以它不会减慢到“python 级别”?其次,VCD 文件是在什么时候加载的?当我导入 SWIG 制作的模块时,还是每次调用函数时?
    • 速度将是可比的(假设是原始程序的 99%)。所以你不应该关心这个。你有这个资源吗? SWIG 只是使 c++ 函数和类在 python 中可用。因此,如果您有一个类 X,您可以将其作为 X 进行访问,如果您有主方法,您可以将其作为主方法进行访问(模块已编译且未链接 - 因此它们不能像程序一样调用)
    【解决方案5】:

    我认为你做错了

    脚本的作用:C++ 程序(不是我制作的,而且我不能很好地用 C++ 编程):接受一个 7 数字数组并返回一个数字,很简单。 Python 脚本(我的,我可以在 python 中编程一点):生成这 7 个数字数组,将它们提供给 c++ 程序,等待答案并将其添加到列表中。然后它创建下一个数组。

    你有这个吗?

    python generate_arrays.py | someC++app | python gather_array.py
    

    这允许您使用机箱上每个 CPU 的每个核心并行运行这三个部分。操作系统确保所有三个同时运行。

    如果您仍未获得 100% 的 CPU 负载,则必须执行类似的操作。

    ( python generate_arrays.py --even | someC++app >oneFile ) & ( python generate_arrays.py --odd | someC++app > anotherFile )
    python gather_array.py oneFile anotherFile
    

    这将运行两个 python generate_arrays.py 副本和两个神奇 C++ 程序的副本。

    您必须重写您的 generate_arrays.py 程序,以便它采用命令行选项。当该选项为 @987654323 @时,您会生成300万个阵列。 When the options is --odd you generate the other 3 million arrays.

    这 (python | c++) & (python | c++) 应该达到 100% cpu 使用率。

    【讨论】: