使用cykthon编译带有dask或joblib多处理的可执行文件导致错误【JAVA教程】

!
也想出现在这里? 联系我们
信息

使用cykthon编译带有dask或joblib多处理的可执行文件导致错误,第1张

概述使用cykthon编译带有dask或joblib多处理的可执行文件导致错误

我正在转换一些串行处理的python作业与dask或joblib多处理。 可悲的是我需要在windows上工作。

当从IPython或从命令行运行python文件与python一切运行良好。

当用cython编译一个可执行文件时,它不再运行正常:一步一步越来越多的进程(无限制和大于请求进程的数量)得到startet并阻止我的系统。

它不知何故感觉像多处理炸d – 但当然, if __name__==\”__main__:\”具有控制块 – 通过从命令行python调用罚款批准。

我的cython调用是cython –embed –verbose –annotate THECODE.PY ,我用gcc -time -municode -DMS_WIN64 -mthreads -Wall -O -I\”PATH_TO_include\” -L\”PATH_TO_libs\” THECODE.c -lpython36 -o THECODE编译gcc -time -municode -DMS_WIN64 -mthreads -Wall -O -I\”PATH_TO_include\” -L\”PATH_TO_libs\” THECODE.c -lpython36 -o THECODE导致一个windows可执行文件THECODE.exe 。

与其他(单一处理)运行良好的代码。

这个问题对于dask和joblib来说似乎是一样的(这可能意味着,dask可以像joblib一样工作)。

有什么build议么?

对于那些对mcve感兴趣的人 :只要从Multiprocessing Bomb获得第一个代码,然后使用上面的cython命令编译代码,就会导致一个可执行文件冒用你的系统。 (我刚刚试过:-))

我只是通过在代码示例中添加一行来显示__name__ :

import multiprocessing def worker(): \”\”\”worker function\”\”\” print(\’Worker\’) return print(\”–>\” + __name__ + \”<–\”) if __name__ == \’__main__\’: jobs = [] for i in range(5): p = multiprocessing.Process(target=worker) jobs.append(p) p.start()

用python运行这段代码的时候会显示出来

15秒的空闲延迟加载windows本机python模块

在windows上,Ctrl-C退出Cython解释器

在windows上的Cython记忆体

将预编译的Cython代码分发到windows

我如何编译windows的cymunk?

__main__ __mp_main__ __mp_main__ __mp_main__ __mp_main__ __mp_main__

(其他输出抑制)。 解释如果决定有效。 在cython和编译显示之后运行可执行文件时

__main__ __main__ __main__ __main__ __main__ __main__

而且越来越多。 因此,模块的工作人员不再像import一样masqueraded ,因此每个工人都试图以recursion方式启动五个新模块。

如何运行cython命令行选项

Cython中的Hello World程序在安装python-dev和链接库之后失败

为什么windows上的Cython扩展取决于pythonXX.dll,而不是MacOSX?

windows Python程序重启(不同生活中的罪过)

在集群上使用Python,Cython和GSL

起初,我很惊讶地发现,你的cython版本以某种方式工作,但它只是一个工作的外观。 但是,有些黑客攻击似乎有可能使其工作。

我在linux上,所以我使用mp.set_start_method(\’spawn\’)来模拟windows的行为。

在spawn -mode中会发生什么? 让我们添加一些sleep ,所以我们可以调查的过程:

#bomb.py import multiprocessing as mp import sys import time def worker(): time.sleep(50) print(\’Worker\’) return if __name__ == \’__main__\’: print(\”Starting…\”) time.sleep(20) mp.set_start_method(\’spawn\’) ## use spawn! jobs = [] for i in range(5): p = mp.Process(target=worker) jobs.append(p) p.start()

通过使用pgrep python我们可以看到,起初只有一个python进程,然后是7(!)不同的pID 。 我们可以通过cat /proc/<pID>/cmdline看到命令行参数。 新进程中有5个命令行

-c \”from multiprocessing.spawn import spawn_main; spawn_main(tracker_fd=5,pipe_handle=11)\” –multiprocessing-fork

和一个:

-c \”from multiprocessing.semaphore_tracker import main;main(4)\”

也就是说,父进程启动6个新的python解释器实例,每个新启动的解释器都通过命令行选项执行从父进程发送的代码,信息通过管道共享。 这6个python实例之一是一个跟踪器,它可以观察整个事物。

好的,如果cythonized + embeded会发生什么? 和普通的python一样,唯一不同的是,可执行文件的启动代替python。 但与python解释器不同的是,它不会执行/不知道命令行参数,所以main函数会一遍又一遍地运行。

有一个简单的解决方法:让bomb -exe启动python解释器

… if __name__ == \’__main__\’: mp.set_executable(<PATH TO PYTHON>) ….

现在这个bomb不再是一个多处理炸d!

但是,目标可能不是有一个Python解释器,所以我们需要让我们的程序知道可能的命令行:

import re …… if __name__ == \’__main__\’: if len(sys.argv)==3: # should start in semaphore_tracker mode nr=List(map(int,re.findall(r\’d+\’,sys.argv[2]))) sys.argv[1]=\’–multiprocessing-fork\’ # this canary is needed for multiprocessing module to work from multiprocessing.semaphore_tracker import main;main(nr[0]) elif len(sys.argv)>3: # should start in slave mode fd,pipe=map(int,sys.argv[2])) print(\”I\’m a slave!,fd=%d,pipe=%d\”%(fd,pipe)) sys.argv[1]=\’–multiprocessing-fork\’ # this canary is needed for multiprocessing module to work from multiprocessing.spawn import spawn_main; spawn_main(tracker_fd=fd,pipe_handle=pipe) else: #main mode print(\”Starting…\”) mp.set_start_method(\’spawn\’) jobs = [] for i in range(5): p = mp.Process(target=worker) jobs.append(p) p.start()

现在,我们的炸d不需要一个独立的python解释器,并在工人完成后停下来。 请注意以下事项:

决定哪种模式bomb应该启动的方式并不是非常安全的,但是我希望你能够获得这个要点

–multiprocessing-fork只是一个金丝雀,它不会做任何事情,只有在那里,看到这里 。

我想结束一个免责声明:我没有太多的多处理模块的经验,没有在windows上,所以我不知道这个解决方案应该建议。 但至少这是一个有趣的:)

注意:更改后的代码也可以与python一起使用,因为执行\”from multiprocessing.spawn import spawn_main; spawn_main(tracker_fd=5,pipe_handle=11)\” –multiprocessing-fork python更改了sys.argv所以代码不再看到原来的命令行和len(sys.argv)是1 。

从ead的答案(或那里给出的想法)的启发下,我找到了一个非常简单的解决方案 – 或者让我们更好地称之为解决方法。

对于我只是改变if子句

if __name__ == \’__main__\’: if len(sys.argv) == 1: main() else: sys.argv[1] = sys.argv[3] exec(sys.argv[2])

做到了。

这个工程的原因是(在我的情况下):当调用原始的.py文件时,工作者的__name__被设置为__mp_main__ (但是所有的进程只是普通的.py文件)。

当运行(cython)编译版本时,worker的name是不可用的,但是worker被调用的是不同的,因此我们可以通过argv中的那个参数来识别它们。 在我的情况下,工人的argv读取

[\’MYPROGRAMM.exe\’,\’-c\’,\’from multiprocessing.spawn import spawn_main; spawn_main(parent_pID=9316,pipe_handle =392)\’,\’–multiprocessing-fork\’]

因此,在argv[2]了用于激活worker的代码,并使用上面的命令执行。

当然,如果你需要编译文件的参数,你需要更大的努力,也许在调用中解析parent_pID。 但就我而言,这只是过分的。

我认为根据提交的错误报告的细节,我可以在这里提供最优雅的解决方案

if __name__ == \’__main__\’: if sys.argv[0][-4:] == \’.exe\’: setattr(sys,\’froZen\’,True) multiprocessing.freeze_support() YOURMAINROUTINE()

在windows上需要freeze_support() – freeze_support() – 参见python多处理文档 。

如果只在该行内运行python,那已经很好了。

但不知何故,cython显然没有意识到这些东西(文档告诉它用py2exe , PyInstaller和cx_Freeze测试)。 这可以通过setattr -call来缓解,只有在编译时才可以使用,因此通过文件扩展来决定。

总结

以上是内存溢出为你收集整理的使用cykthon编译带有dask或joblib多处理的可执行文件导致错误全部内容,希望文章能够帮你解决使用cykthon编译带有dask或joblib多处理的可执行文件导致错误所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

© 版权声明
THE END
喜欢就支持一下吧
点赞178 分享
评论 抢沙发

请登录后发表评论

    请登录后查看评论内容