一个持有GIL的简单的Python函数

4
我想测试我的应用程序对持有GIL的函数的响应情况。是否有一种方便的函数可以持有GIL一段可预测(甚至是显著的)时间?我的理想函数会像time.sleep一样运行,但与sleep不同,它将持有GIL。

2
函数不持有GIL(也不能持有)。Python解释器循环持有GIL。你为什么认为你需要这个? - Martijn Pieters
2
我认为我需要这个,因为我想测试我的分布式系统在运行会导致解释器循环长时间持有GIL的函数时的表现:http://distributed.readthedocs.io/en/latest/ - MRocklin
2
有一些函数可以从Python中访问,它们持有全局解释器锁(GIL)。这些函数可能会调用不释放GIL的C代码。 - MRocklin
2
我不确定你从哪里得到这个信息。我确实使用线程进行计算,我确实需要担心GIL,并且对于我的目的来说没有太大的区别。如果有人调用一个函数,比如pandas.DataFrame.merge,它会导致GIL长时间被占用,那么我的I/O将会暂停一段时间。因为这个原因我得到了糟糕的结果,我想测试一下。 - MRocklin
我很好奇这里是否有任何进一步的发展。具体来说,我对于pandas.DataFrame.merge如何阻塞GIL感到困惑。在需要与分布式情况下的工作人员进行一致通信的情况下,是否应该每n个tick提供这种机会?鉴于Numpy操作发生在GIL之外,什么特定方面会阻止/防止工作人员的通信?除非Numpy步骤构成了一个“长tick”(解释器指令),它本身创建了一个超时(?)。 - kuanb
显示剩余4条评论
2个回答

4

一种简单但不太正规的持有GIL的方式是使用re模块和已知较慢的匹配方法:

import re
re.match(r'(a?){30}a{30}', 'a'*30)

在我的计算机上,使用Python 2.7.14持有GIL达48秒(3.6.3几乎需要同样长的时间)。然而,这依赖于实现细节,并且如果re模块得到改进,可能会停止工作。
更直接的方法是编写一个只休眠的c模块。 Python C扩展不会自动释放GIL(与ctypes不同)。请参考hellomodule示例here,并将printf()替换为调用sleep()(或Windows等效项)。一旦构建了该模块,您就可以在任何地方使用具有GIL保持功能的函数。

2

您可以在“PyDLL”模式下使用C库的sleep函数。

# Use libc in ctypes "PyDLL" mode, which prevents CPython from
# releasing the GIL during procedure calls.
_libc_name = ctypes.util.find_library("c")
if _libc_name is None:
    raise RuntimeError("Cannot find libc")
libc_py = ctypes.PyDLL(_libc_name)
...
libc_py.usleep(...)

(详见 https://gist.github.com/jonashaag/d455671003205120a864d3aa69536661,其中详细说明如何对参考文献进行腌制(pickle),例如在分布式计算环境中使用时。)

1
libc函数可以使用libc_py = ctypes.PyDLL(None)访问而无需名称,因此您可以跳过查找步骤。 - minrk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接