标签: gil

从 C 调用 python 函数作为回调。处理 GIL 的正确方法是什么?

我正在使用cytpes包装 C api。api 函数之一允许您注册回调。我使用CFUNCTYPEto 来指定函数的类型,并CFUNCTYPE从我的 python 库的用户提供的 python 函数中创建一个实例,然后我将其传递给 C 函数(使用ctypesapi调用)。

我知道ctypes调用释放GIL. 我想知道当 C 库函数调用我的 python 回调函数时会发生什么。是否ctypes重新获得GIL

文件说:

注意:CFUNCTYPE()只要在 C 代码中使用对象,请确保保留对对象的引用。ctypes没有,如果你不这样做,它们可能会被垃圾收集,在进行回调时会导致程序崩溃。另外,请注意,如果在 Python 控制之外创建的线程中调用回调函数(例如,通过调用回调的外部代码),则ctypes在每次调用时都会创建一个新的虚拟 Python 线程。这种行为在大多数情况下是正确的,但它意味着存储的值threading.local不会在不同的回调中存活,即使这些调用是从同一个 C 线程进行的。

它没有说任何关于GIL. 是不是说一切都由我来处理?

python ctypes callback gil

5
推荐指数
1
解决办法
832
查看次数

boost.python c++ multithreading

I'm writing a python program that includes a c++ module (.so, using boost.python).
I'm starting several python threads that run a c++ function.

This is how the C++ code looks like:

#include <boost/python.hpp>
using namespace boost;
void f(){
    // long calculation

    // call python function

    // long calculation
}

BOOST_PYTHON_MODULE(test)
{
    python::def("f", &f);
}
Run Code Online (Sandbox Code Playgroud)

And the python code:

from test import f
t1 = threading.Thread(target=f)
t1.setDaemon(True)
t1.start()
print "Still running!"
Run Code Online (Sandbox Code Playgroud)

I encounter a problem: the "Still running!" …

c++ python multithreading gil boost-python

5
推荐指数
1
解决办法
2473
查看次数

使用 nogil 在 Cython 中处理列表列表

在 Python 中,我有一个列表列表作为输入:

input = [[0,1,2],[0,3,4,5],[0,6]]
Run Code Online (Sandbox Code Playgroud)

实际上,子列表的数量有数万个。每个子列表的长度可能相差很大,从零或一个值到数百个值。

我想将输入数据作为某种 2D 结构传递给将处理它的 Cython 模块。我希望在多个核心上处理数据,因此我使用prangewith nogil=True

from cython.parallel import prange

cpdef int my_func(long[:,:] arr):
    cdef int i,j
    for i in prange(arr.shape[0], nogil=True):
        for j in range(arr.shape[1]):
                    # Do something
            pass
    return 42
Run Code Online (Sandbox Code Playgroud)

我看到以下解决方案:

  1. 将列表的列表放入 2D ndarray 中。但由于每个子列表的长度相差很大,ndarray并不是一个理想的数据结构
  2. 修改my_func以接受列表的列表。问题是部分代码是在没有 GIL 的情况下执行的,因此无法访问 python 对象。

有没有人对如何解决这个问题有建议,最好有代码?

python multiprocessing cython gil

5
推荐指数
1
解决办法
1363
查看次数

Python 上下文中的运行时是什么?它由什么组成?

在这个问题的上下文中什么是“运行时”?(/sf/ask/273038461/)

我试图了解 python 运行时由什么组成。我的猜测是:

  1. 包含所有运行时变量的 python 进程。
  2. 吉尔吉斯斯坦
  3. 底层解释器代码(CPython 等)。

现在,如果这是正确的,我们是否可以说 python 中的多处理创建了多个运行时并且一个 python 进程是我们可以直接与运行时相关联的东西?(我认为这是正确的选择)

或者,每个 python 线程都有自己的堆栈,与父进程在相同的 GIL 和内存空间上工作,可以被称为具有单独的运行时?

或者,不管有多少线程或进程正在运行,它都会在一个运行时下运行?

简单来说,Python 上下文中运行时的定义是什么?

PS:我理解线程和进程之间的区别。GIL:我理解这些影响,但我不理解。

python terminology runtime multiprocessing gil

5
推荐指数
1
解决办法
4612
查看次数

为什么 time.sleep(...) 不受 GIL 的影响?

根据我在研究 Python GIL 时的理解,一次只能执行一个线程(谁持有锁)。然而,如果这是真的,那么为什么这段代码只需要 3 秒的执行时间,而不是 15 秒呢?

import threading
import time

def worker():
    """thread worker function"""
    time.sleep(3)
    print 'Worker'

for i in range(5):
    t = threading.Thread(target=worker)
    t.start()
Run Code Online (Sandbox Code Playgroud)

根据对线程的直觉,我原以为这需要 3 秒,但确实如此。但是在了解了 GIL 并且可以立即执行一个线程之后,现在我看这段代码并想,为什么不花 15 秒?

python gil

5
推荐指数
2
解决办法
1102
查看次数

有没有办法使用纯 python 为纯函数释放 GIL?

我想我一定错过了什么;这似乎是正确的,但我看不出有什么方法可以做到这一点。

假设你在 Python 中有一个纯函数:

from math import sin, cos

def f(t):
    x = 16 * sin(t) ** 3
    y = 13 * cos(t) - 5 * cos(2*t) - 2 * cos(3*t) - cos(4*t)
    return (x, y)
Run Code Online (Sandbox Code Playgroud)

是否有一些内置功能或库提供某种类型的包装器,可以在函数执行期间释放 GIL?

在我的脑海中,我在想一些事情

from math import sin, cos
from somelib import pure

@pure
def f(t):
    x = 16 * sin(t) ** 3
    y = 13 * cos(t) - 5 * cos(2*t) - 2 * cos(3*t) - cos(4*t)
    return (x, y)
Run Code Online (Sandbox Code Playgroud)

为什么我认为这可能有用?

因为目前只对 I/O 密集型程序有吸引力的多线程,一旦这些功能长期运行就会变得有吸引力。做类似的事情 …

python multiprocessing gil python-asyncio

5
推荐指数
1
解决办法
90
查看次数

ThreadPoolExecutor 如何利用 32 个 CPU 核心来执行 CPU 密集型任务

来自ThreadPoolExecutor

在 version 3.8 中更改: max_workers 的默认值更改为 min(32, os.cpu_count() + 4)。此默认值为 I/O 绑定任务保留至少 5 个工作线程。它最多使用 32 个 CPU 核心来执行释放 GIL 的 CPU 密集型任务。它避免了在多核机器上隐式使用大量资源。

根据我对 GIL 的理解,基于线程的并发仅适用于 I/O 绑定任务。对于 CPU 密集型任务,基于线程的并发是不可能的,这意味着对于 CPU 密集型任务,GIL 仅强制单线程执行。我的理解似乎与 中的粗体行相矛盾ThreadPoolExecutor。我在这里误解了什么?

此外,什么是

释放GIL

意思是?CPU 密集型任务不会保留 GIL(除非它被抢占)吗?

这个答案来看,我怀疑这与

大部分时间都花在旨在发布 GIL 的外部库上(如 NumPy)

这是否意味着只要线程在某些专门设计的“旨在释放 GIL”的外部库中执行 CPU 密集型任务,CPU 密集型任务的基于线程的并发实际上是可能的?

python multithreading gil python-3.x

5
推荐指数
1
解决办法
1422
查看次数

是否有可能在阻止并可能回调为Python的C函数之前释放GIL?

我正在包装一个执行阻塞操作(选择)的C函数,然后处理传入的消息.我的理解是,当一个C函数要阻塞时,在允许其他线程运行的同时调用它的正确方法是:

Py_BEGIN_ALLOW_THREADS                                                  
blocking_function();
Py_END_ALLOW_THREADS
Run Code Online (Sandbox Code Playgroud)

但是,它发生此函数将回调指针作为参数.在处理由C函数预处理的传入消息时调用此回调.我已经成功地将这个回调包装在一个调用的函数中PyEval_CallObject(),允许我传递一个Python回调.

现在我正在添加线程支持,我想知道是否可以同时:

  • 在调用此阻止操作之前释放GIL.
  • 让这个阻塞操作安全地回调到python解释器.

这会导致问题吗?如果是这样,有办法吗?

谢谢.

python gil python-multithreading python-bindings

4
推荐指数
1
解决办法
749
查看次数

并行文件匹配,Python

我正在尝试改进扫描文件中的恶意代码的脚本.我们在文件中有一个正则表达式模式列表,每行一个模式.这些正则表达式适用于grep,因为我们当前的实现基本上是一个bash脚本find\grep combo.bash脚本在我的基准测试目录上需要358秒.我能够编写一个在72秒内执行此操作的python脚本,但希望进一步提高.首先,我将发布基本代码然后调试我尝试过:

import os, sys, Queue, threading, re

fileList = []
rootDir = sys.argv[1]

class Recurser(threading.Thread):

    def __init__(self, queue, dir):
    self.queue = queue
    self.dir = dir
    threading.Thread.__init__(self)

    def run(self):
    self.addToQueue(self.dir)

    ## HELPER FUNCTION FOR INTERNAL USE ONLY
    def addToQueue(self,  rootDir):
      for root, subFolders, files in os.walk(rootDir):
    for file in files:
       self.queue.put(os.path.join(root,file))
      self.queue.put(-1)
      self.queue.put(-1)
      self.queue.put(-1)
      self.queue.put(-1)
      self.queue.put(-1)
      self.queue.put(-1)
      self.queue.put(-1)
      self.queue.put(-1)
      self.queue.put(-1)
      self.queue.put(-1)
      self.queue.put(-1)
      self.queue.put(-1)
      self.queue.put(-1)
      self.queue.put(-1)
      self.queue.put(-1)
      self.queue.put(-1)
      self.queue.put(-1)
      self.queue.put(-1)
      self.queue.put(-1)
      self.queue.put(-1)

class Scanner(threading.Thread):

    def __init__(self, queue, patterns):
    self.queue = queue …
Run Code Online (Sandbox Code Playgroud)

python string parallel-processing multithreading gil

4
推荐指数
2
解决办法
4229
查看次数

Python GIL:是django save()阻塞?

我的django应用程序将django模型保存到远程数据库.有时保存是突发性的.为了将应用程序的主线程(*thread_A*)从将多个对象保存到数据库的时间中解放出来,我想到了将模型对象转移到一个单独的线程(*thread_B*)使用collections.deque并具有*thread_B*save他们顺序.

但我不确定这个计划.save()返回新数据库条目的id,因此只有在数据库响应后才会"结束",这是在事务结束时.

难道django.db.models.Model.save()真的阻止GIL -wise并释放其他的Python线程的交易?

python django multithreading transactions gil

4
推荐指数
1
解决办法
1876
查看次数