我需要在 Cython 中使用 `nogil`

2024-03-27

我有一些 Cython 代码,我想尽快运行。我需要释放 GIL 才能执行此操作吗?

假设我的代码与此类似:

import numpy as np

# trivial definition just for illustration!
cdef double some_complicated_function(double x) nogil:
    return x

cdef void func(double[:] input) nogil:
    cdef double[:] array = np.zeros_like(input)
    for i in range(array.shape[0]):
        array[i] = some_complicated_function(input[i])

我收到了一大堆错误消息np.zeros_like行类似于:

nogilcode.pyx:7:40: Calling gil-requiring function not allowed without gil
nogilcode.pyx:7:29: Accessing Python attribute not allowed without gil
nogilcode.pyx:7:27: Accessing Python global or builtin not allowed without gil
nogilcode.pyx:7:40: Constructing Python tuple not allowed without gil
nogilcode.pyx:7:41: Converting to Python object not allowed without gil

我需要找到一种调用方式吗np.zeros_like没有GIL?或者找到其他不需要 GIL 的分配数组的方法?


注意:这是一个自我回答的问题,旨在消除有关 Cython 和 GIL 的一些常见误解(当然,也欢迎您回答它!)。

第二个注意事项:我已经为 Cython 做出了足够的贡献,因此我应该在这里注明(鉴于我正在提出这个主题)


No-你可能不知道need释放 GIL。

GIL(全局解释器锁)的基本功能是通过确保一次只有一个Python线程能够运行来确保Python的内部机制不受竞争条件的影响。然而,仅仅保留 GIL 并不会减慢你的代码速度。

您应该释放 GIL 的两个(相关)场合是:

  1. Using Cython的并行机制 https://cython.readthedocs.io/en/latest/src/userguide/parallelism.html。的内容prange例如循环需要是nogil.

  2. 如果您希望其他(外部)Python 线程能够同时运行。

    A。如果您有一个不需要 GIL 的大型计算/IO 密集型块,那么释放它可能是“礼貌”的做法,只是为了让想要执行多线程的代码用户受益。然而,这主要是有用的而不是必要的。

    b. (非常非常偶尔)有时用短命令短暂释放 GIL 很有用with nogil: pass堵塞。这是因为 Cython 不会自发释放它(与 Python 不同),因此如果您正在等待另一个 Python 线程完成任务,这可以避免死锁。除非您使用 Cython 编译 GUI 代码,否则此子点可能不适用于您。


可以在没有 GIL 的情况下运行的 Cython 代码(不调用 Python,纯 C 级数字运算)是often高效运行的代码类型。有时这会给人这样的印象:相反的情况是正确的,技巧是释放 GIL,而不是他们正在运行的实际代码。不要被这个误导——无论有没有 GIL,你的(单线程)代码都会以相同的速度运行。

因此,如果您有一个很好的快速 Numpy 函数,它可以在大数据块上快速完成您想要的操作,但只能使用 GIL 调用,那么只需调用它即可 - 没有什么坏处!


最后一点:即使在nogil块(例如prange循环),如果需要,您可以随时取回 GIL:

with gil:
    ... # small block of GIL requiring code goes here

尽量不要太频繁地执行此操作(获取/释放它需要时间,当然,一次只能有一个线程运行此块),但同样,这是在需要时执行小型 Python 操作的一种好方法。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

我需要在 Cython 中使用 `nogil` 的相关文章

随机推荐

  • 如何将大型对象/数组序列化为 JSON

    我的应用程序需要生成一个具有大对象的 jsondata数组类型的属性 数组在收集数据库输出时需要保留在内存中 并且某些属性只有在数组完成后才能确定 复杂性 数组是基于数字的 并且必须在 json 输出中出现 因此直接json encode
  • 使用内联“宽度”时省略像素

    这是一个有点愚蠢的问题 但对我来说理解很重要 据我所知 在 HTML 中使用内联 width 属性时 允许省略 px 除非使用百分比 20 否则将自动被理解为 20px 我的问题是 即使不需要 px 使用它是否错误 这段代码对我来说看起来非
  • 如何更改/usr/bin/env?

    我有使用的脚本 usr bin env ruby但我已经改用 Ruby Enterprise Edition 而不是 Ubuntu 服务器附带的默认 ruby 因此 当我尝试运行脚本时 它们会崩溃 如何添加 Ruby EE 路径 usr b
  • 如何使用 Apache POI 对 Excel 工作表中的行应用背景颜色?

    我正在使用 Apache POI 将数据导出到 Excel 工作表中 效果很好 问题是我需要在生成 Excel 工作表时为 Excel 工作表中的几行应用黄色背景颜色 请告诉我如何在生成时为 Excel 工作表的行应用背景颜色 谢谢 雷迪
  • 单父实体的核心数据性能

    我正在创建一个与核心数据一起使用的框架 在核心数据类上使用我的框架的要求之一是 您想要拥有框架功能的任何实体都需要是我提供给您的实体的子实体和子类 为此 我将该对象称为 Foo 今天我意识到 Core Data 将作为 Foo 子实体的所有
  • 在 Studio 中将大写字母转换为驼峰字母的简单方法?

    我有一堆 C 定义需要移植到 C C 定义是带下划线的大写字母 Net 枚举应该是驼峰式 有什么办法可以自动转换它们吗 一些我不知道的工具 或者也许是一个神奇的正则表达式 eg BOOTSTRAP NOT SUPPORTED gt Boot
  • 如何在进程的内存中搜索特定字符串?

    我对基础知识感兴趣 我不知道从哪里开始 我创建了这个测试程序 include
  • 如何在 LinqPad 中执行 ODATA 扩展

    我正在使用 LINQPad 连接到本地 CRM 组织上的 ODATA 服务 但我不知道如何使用 LINQPad 执行 联接 或遍历关系 这是我的网址 OrganizationData svc New locationSet select n
  • 如何在 Mac 上安装 NVM

    我尝试使用以下命令在 Mac 上安装 NVM curl o https raw githubusercontent com nvm sh nvm v0 39 1 install sh bash 但是 我收到一条错误消息 语法错误接近意外的
  • MPI+p 线程。程序卡在 MPI_Ssend 和 MPI_Recv 上

    我已经调试了这个程序2周了 它只有 93 行 但我仍然找不到错误 请帮我 这个程序在我的笔记本电脑上运行正常 但是当我在我的实验室 上海超算中心和济南超算中心的集群上运行时 就卡住了 这个程序的逻辑非常简单 有 2 个 MPI 进程 一个是
  • php.ini:哪一个?

    我从旧的 apache 迁移到 nginx 和 php 5 3 10 当我尝试修改 php ini 以满足我的需要时 我发现有 3 个 locate php ini etc php5 cgi php ini etc php5 cli php
  • 如何让 EF 将空字符串保留为 NULL?

    在我的域中 NULL 和空字符串之间没有重要区别 如何让 EF 忽略两者之间的差异并始终将空字符串保留为 NULL 空字符串不是字符串属性的默认值 因此这意味着您的代码正在某处设置空字符串 在这种情况下 您有责任处理 如果您在 POCO 中
  • Windows 安装程序中的主要与次要升级

    是否有任何理由不设置安装 以便始终完成主要升级并更改产品代码 我发现支持不同类型的安装需要更多代码 并且 修复 安装似乎通过重大升级更容易工作 而且需要安装的应用程序不是很大 因此不需要 服务包 或补丁安装程序 不会 如果您的应用程序很小并
  • 使用迭代器将数组划分为大小不等的部分

    我有一个数组 需要将其分为 3 元素子数组 我想用迭代器来做到这一点 但最终我迭代到了数组的末尾并出现段错误即使我没有取消引用迭代器 给定 auto foo 1 2 3 4 5 6 7 8 9 10 我正在做 auto bar cbegin
  • ef4 导致 Web 服务中的循环引用

    我有一个 Reason 对象 public class Reason public virtual long Id get set public virtual string Name get set public virtual Comp
  • php 中的 QR 码,无需使用现已弃用的 Google Charts API

    有谁知道有一个 PHP 类可以在您的服务器上生成二维码 而不是依赖现已弃用的 Google Charts API 该 API 并不总是存在 我还认为 如果在服务器上完成批量 QR 码生成将会更快 我还会考虑使用基于 JS 或 Jquery
  • HTML5 音频回调在 safari/iOS 上失败

    我构建了一个应用程序 旨在通过使用 结束 事件在第一个声音完成时播放每个声音 在我的初始版本中 每个声音都有自己的音频元素 结果如下 function play next audio speaker audio sounds i get 0
  • 如何应用多个 DSC 配置?

    这是我的例子 Config AllNodes NodeName localhost PSDscAllowPlainTextPassword True Configuration LocalAdmin Param String Node lo
  • Gnuplot:多个堆叠直方图,每组使用相同的键

    我正在尝试创建一个具有多个堆叠直方图的图 如示例 8here http gnuplot sourceforge net demo histograms html 但对于我的数据来说 每组都有相同的四个类别 如何更改颜色和键 以便每个堆叠列的
  • 我需要在 Cython 中使用 `nogil`

    我有一些 Cython 代码 我想尽快运行 我需要释放 GIL 才能执行此操作吗 假设我的代码与此类似 import numpy as np trivial definition just for illustration cdef dou