我的python程序肯定是cpu受限的,但是40%到55%的时间是在z3解算器中的C代码中执行的(它对gil一无所知),每次调用C函数(z3_optimize_check
)都要花费将近一分钟的时间来完成(到目前为止,parallel_enable
参数仍然导致该函数在单线程模式下工作,并且堵塞主螺纹)。你知道吗
我不能使用多重处理,因为z3u对象是不可序列化友好的(除非这里有人能证明不是这样)。由于它们是多个任务(其中每个任务在dict中为其他任务添加更多的z3工作),我最初直接设置mulithreading。但是Gil对性能的伤害肯定大于它的好处(尤其是超读),尽管它花费了大量的时间在解算器上。你知道吗
但是,如果我在z3py模块中手动(通过threading.Lock.aquire()
)设置了一个阻塞互斥锁,就在从C代码切换之后,它只允许其他线程在所有其他线程都执行解算器工作的情况下运行,这会不会消除gil性能损失(因为它们在执行python代码时只有1个线程,而且总是这样)在z3_optimize_check
之前释放锁之前是同一个吗?
我的意思是,使用threading.Lock.aquire()
会不会触发对PyEval_SaveThread()
的调用,就好像z3是直接做的一样?
我想你误解了。z3以并行模式运行意味着您从一个Python线程调用它,然后它为自己生成多个OS级线程,执行该任务,清理线程并为您返回结果。它不能奇迹般地使Python在没有GIL的情况下运行。
从Python的角度来看,它仍然一次只做一件事,那就是调用z3。它一直在控制着吉尔。因此,如果您看到在运行计算时使用了多个CPU核心/线程,这就是z3的并行模式的效果,即内部分支到多个线程。你知道吗
还有一件事,释放GIL,比如阻塞I/O操作。这不是魔法造成的,有一个呼叫对:
这些是C调用,因此扩展开发人员可以访问它们。当开发人员知道代码将运行很长时间,而不需要访问Python内部构件时,就可以使用
PyEval_SaveThread()
,然后Python可以继续处理其他Python线程。当长线程完成任何操作时,线程可以重新介绍自己并使用PyEval_RestoreThread()
申请GIL。但是,只有开发人员让这些事情发生,这些事情才会发生。而对于z3,情况可能并非如此。你知道吗
直接回答您的问题:不,Python代码不能释放GIL并使其保持释放状态,因为GIL是Python线程在运行时必须持有的锁。因此,每当Python“指令”返回时,GIL就会再次被持有。你知道吗
很明显,我设法不包含我想要的链接,所以它们在第https://docs.python.org/3/c-api/init.html#thread-state-and-the-global-interpreter-lock页(链接的段落讨论了我很快总结的内容)。你知道吗
Z3是开源的(https://github.com/Z3Prover/z3),源代码既不包含
PyEval_SaveThread
,也不包含包装快捷方式Py_BEGIN_ALLOW_THREADS
字符序列。你知道吗但是,它有一个并行Python示例,顺便说一句https://github.com/Z3Prover/z3/blob/master/examples/python/parallel.py,其中
所以我假设它可能会被测试并使用
multiprocessing
。你知道吗相关问题 更多 >
编程相关推荐