释放 GIL 的成本是多少?

发布于 2024-12-11 16:59:37 字数 305 浏览 0 评论 0原文

假设我有一个 C 扩展函数,它执行完全独立于 Python 解释器的操作。有什么理由释放 GIL 吗?

例如,是否有任何理由不编写这样的代码(除了可读性和避免微优化等问题之外——这些事情很重要,但与我的问题并不真正相关)?

Py_BEGIN_ALLOW_THREADS
    a = 1 + 1;
Py_END_ALLOW_THREADS

显然,这是很简单的代码,性能可能不会太重要。但是是否有任何性能原因在这里释放GIL?或者应该只为 CPU 密集型代码释放 GIL?

Let's suppose I have a C extension function that does something that is completely independent of the Python interpreter. Is there any reason not to release the GIL?

For example, is there any reason not to write code like this (apart from issues like readability and avoiding micro-optimization - things that are important, but not really relevant to my question)?

Py_BEGIN_ALLOW_THREADS
    a = 1 + 1;
Py_END_ALLOW_THREADS

Clearly, this is trivial code where performance probably won't matter too much. But is there any performance reason not to release the GIL here? Or should the GIL only be released for more CPU-intensive code?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

旧竹 2024-12-18 16:59:37

GIL 是一个普通的互斥体。锁定或解锁无竞争互斥锁的成本非常低,并不比更改全局变量的成本高多少。但是,如果您经常锁定和解锁有争议的互斥体,则互斥体的成本可能会变得很大。

因此,这通常不是一个好主意:

Py_BEGIN_ALLOW_THREADS
    a = 1 + 1;
Py_END_ALLOW_THREADS

这里发生的情况是您正在解锁一个互斥锁,然后您尝试立即再次锁定该互斥锁。如果这是两个大块代码之间的中断,那么它就会为另一个线程提供运行的机会。但如果线程粒度没有问题,则保持锁定即可。

因此,在这种情况下这是一个好主意:

very_long_computation_requires_gil();
Py_BEGIN_ALLOW_THREADS;
a = a + i;
Py_END_ALLOW_THREADS;
very_long_computation_also_requires_gil();

在不了解上下文的情况下确实不可能做出有根据的猜测,并且在不运行测试的情况下通常仍然很困难。

The GIL is an ordinary mutex. The cost of locking or unlocking an uncontested mutex is extremely low, not much more than the cost of changing a global variable. However, if you lock and unlock a contested mutex very often, the cost of the mutex can become significant.

So, this is not usually a good idea:

Py_BEGIN_ALLOW_THREADS
    a = 1 + 1;
Py_END_ALLOW_THREADS

What is happening here is you are unlocking a mutex that you try to lock again immediately afterwards. If this is a break between two large chunks of code, then it gives another thread a chance to run. But if you don't have problems with threading granularity, just keep the lock.

So it's a good idea in this context:

very_long_computation_requires_gil();
Py_BEGIN_ALLOW_THREADS;
a = a + i;
Py_END_ALLOW_THREADS;
very_long_computation_also_requires_gil();

It's really impossible to make an educated guess without knowing the context, and it's often still difficult without running tests.

随心而道 2024-12-18 16:59:37

如果您有一个 C 扩展函数,它执行完全独立于 Python 解释器的操作,那么释放 GIL 通常是一个好主意。唯一的缺点是等待取回 GIL。在 Python 3.2 中,您必须等待至少 1/20 秒。

If you have a C extension function that does something that is completely independent of the Python interpreter, then releasing the GIL is usually a good idea. The only downside is waiting to get the GIL back. In Python 3.2, you have to wait a minimum of 1/20th of second.

捎一片雪花 2024-12-18 16:59:37

有什么理由不释放 GIL 吗?

如果 C 扩展调用不可重入代码,那么如果多个 Python 线程同时调用该扩展,则可能会出现问题。因此,您可能希望避免在此类扩展中释放 GIL,以防止这种情况发生(当然,您可以在 Python 级别或 C 级别创建自己的互斥体,以在不影响其他线程的情况下实现此目的)。

或者应该只为 CPU 密集型代码释放 GIL?

释放 GIL 的另一个主要原因是在调用阻塞的 C 扩展(例如套接字上的阻塞读取)以允许其他线程运行时。这正是 Python 解释器本身在线程中执行阻塞操作时发生的情况。

Is there any reason not to release the GIL?

If the C extension calls non re-entrant code, then you could have problems if multiple Python threads call in to the extension at the same time. So you may want to avoid releasing the GIL in such extensions to protect against this happening (of course you could create your own mutex at the Python level or C level to achieve this without affecting other threads).

Or should the GIL only be released for more CPU-intensive code?

Another main reason for releasing the GIL is when calling a C extension that blocks (such as a blocking read on a socket) to enable other threads to run. This is exactly what happens when the Python interpreter itself executes a blocking operation in a thread.

红颜悴 2024-12-18 16:59:37

专家们仍在对 GIL 进行调整和测试。

这是关于老问题的新想法:
inside-look-at-gil-removal -patch

您还可以考虑尝试 Stackless Python(无 GIL)或 PyPy(带有即时编译器的 Python)。

Experts are still tweaking and testing about GIL.

This are new ideas about a old problem :
inside-look-at-gil-removal-patch

You can also consider to try Stackless Python ( no GIL ) or PyPy ( Python with Just-In-Time compiler ).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文