gpt4 book ai didi

cython - 使用函数指针指向没有 gil 的类的方法

转载 作者:行者123 更新时间:2023-12-03 09:19:04 28 4
gpt4 key购买 nike

我的部分工作需要大量计算,但它们通常相当简单,原则上可以很容易地与 Cython 的 prange 并行完成,需要 nogil。但是,鉴于我尝试编写 Cython 代码,重点是将 cdef 类作为构建 block ,我遇到了问题。

假设我有一个数值积分例程或类似的例程,它将函数指针作为输入

ctypedef double (* someFunctionPointer) (double tt) nogil

cdef double integrationRoutine(someFunctionfointer ff) nogil:
# Doing something
# ...
return result

现在我的每个集成点实际上是一个“更大的”模拟(很多参数等等我加载/设置/输入或其他),它是在一个类中实现的。所以我最初的方法是做类似的事情

cdef class SimulationClass:

cdef double simulationFunctionPointer(SimulationClass self, double tt) nogil:
# ...

我认为我可以将“simulationFunctionPointer”交给“integrationRoutine”,这样就可以了。由于 self 参数,这当然行不通。

我所有的解决方法都需要

  • 不使用 cdef 类,而是使用 C 结构之类的东西(如果 SimulationClass 引用许多其他类、参数等,则会很棘手)
  • 使用 gil 执行某些操作(因为我想使用SimulationClass;我编写了一些独立函数,该函数将SimulationClass 视为 void*,但随后我需要再次将其强制转换为SimulationClass,这需要 gil)

有什么建议或想法可以解决这个问题吗?我的第一种方法可以用其他语言(例如 C++)吗?

干杯

最佳答案

您可以在需要 GIL 的 block 周围使用 with gil:,然后在需要占用大部分运行时间的重要内部 block 周围使用 with nogil:。举一个简单的例子

from cython.parallel import prange

cdef class Simulation:
cdef double some_detail

def __cinit__(self,double some_detail):
self.some_detail = some_detail

def do_long_calculation(self, double v):
with nogil:
pass # replace pass with something long and time-consuming
return v*self.some_detail


def run_simulations(int number_of_simulations):
cdef int n
for n in prange(number_of_simulations,nogil=True):
with gil: # immediately get the gil back to do the "pythony bits"
sim = Simulation(5.3*n)
sim.do_long_calculation(1.2) # and release again in here"

假设do_long_calculation中的nogil部分的运行时间比您设置和传递模拟的部分长(可以与do_long_calculation并行运行) code>,但不与其本身一起)这是相当有效的。


关于将绑定(bind)方法转换为函数指针的附加小评论:在 Cython 中你真的很难做到这一点。我最好的解决方法是使用 ctypes (或者也可能是 cffi),它可以将任何 Python 可调用对象转换为函数指针。他们这样做的方式似乎涉及一些您可能不想复制的运行时代码生成。您可以将此方法与 Cython 结合使用,但它可能会增加函数调用的一些开销(因此请确保 do_long_calculation 实际上很长!)

以下作品(归功于http://osdir.com/ml/python-cython-devel/2009-10/msg00202.html)

import ctypes
# define the function type for ctypes
ftype = ctypes.CFUNCTYPE(ctypes.c_double,ctypes.c_double)

S = Simulation(3.0)
f = ftype(S.do_long_calculation) # create the ctypes function pointer

cdef someFunctionPointer cy_f_ptr = (<someFunctionPointer*><size_t>ctypes.addressof(f))[0] # this is pretty awful!

关于cython - 使用函数指针指向没有 gil 的类的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34878942/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com