我的部分作品需要大量的计算,但它们通常相当简单,原则上可以很容易地与Cython的prange平行完成,需要nogil。但是,考虑到我试图编写我的Cython代码,重点是将cdef类作为构建块我遇到了问题。
我们说我得到了一个数值积分例程或类似的函数指针作为输入
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" to" integrationRoutine"没关系由于自我论证,这当然不起作用。
我所有的解决方案都需要
任何建议或想法如何解决这个问题?我的第一种方法是否可以用于其他语言,如C ++?
干杯
答案 0 :(得分:4)
您可以在需要GIL的块周围使用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"
,然后在占用大部分运行时间的重要内部块周围使用nogil
。举一个简单的例子
do_long_calculation
如果do_long_calculation
中的do_long_calculation
部分的运行时间比您设置的部分长,并且通过模拟(可以与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中真的很难做到这一点。我最好的工作是使用ctypes(或者也可能是cffi)可以将任何Python可调用的函数转换为函数指针。他们这样做的方式似乎涉及一些你可能不想复制的运行时代码生成。您可以将此方法与Cython结合使用,但它可能会给函数调用增加一些开销(因此请确保$computername=$args[0]
if ($args -eq $null) { $computername = Read-Host "enter computer name" }
Get-ADComputer -Id $computername -Properties * | select name,description
实际上很长!)
以下作品(归功于http://osdir.com/ml/python-cython-devel/2009-10/msg00202.html)
numbers = []
def easy_mode():
with open("aa.txt","r") as f:
for i in range(9):
numbers.append(f.readline().strip())
print(numbers)
from random import randint
for i in range(9):
print(numbers[randint(0,8)])