Python 我可以在用ctypes包装的函数上使用dask.delayed吗?

Python 我可以在用ctypes包装的函数上使用dask.delayed吗?,python,ctypes,dask,dask-delayed,Python,Ctypes,Dask,Dask Delayed,我们的目标是使用dask.delayed来并行化我代码中一些“令人尴尬的并行”部分。代码涉及调用python函数,该函数使用ctypes包装c函数。为了理解我遇到的错误,我写了一个非常基本的例子 c功能: double zippy_sum(double x, double y) { return x + y; } python: from dask.distributed import Client client = Client(n_workers = 4) client import o

我们的目标是使用
dask.delayed
来并行化我代码中一些“令人尴尬的并行”部分。代码涉及调用python函数,该函数使用
ctypes
包装c函数。为了理解我遇到的错误,我写了一个非常基本的例子

c功能:

double zippy_sum(double x, double y)
{
return x + y;
}
python:

from dask.distributed import Client
client = Client(n_workers = 4)
client

import os
import dask
import ctypes

current_dir = os.getcwd() #os.path.abspath(os.path.dirname(__file__))
_mod = ctypes.cdll.LoadLibrary(os.path.join(current_dir, "zippy.so"))

_zippy_sum = _mod.zippy_sum
_zippy_sum.argtypes = [ctypes.c_double, ctypes.c_double]
_zippy_sum.restype = ctypes.c_double

def zippy(x, y):

    z = _zippy_sum(x, y)

    return z

result = dask.delayed(zippy)(1., 2.)
result.compute()
回溯:

---------------------------------------------------------------------------KeyError回溯(最近的呼叫 最后) ~/.edm/envs/evaxi3.6/lib/python3.6/site-packages/distributed/worker.py 在具有_cache_lock的dumps_函数(func)3286中: ->3287 result=cache_dumps[func]3288,KeyError除外:

~/.edm/envs/evaxi3.6/lib/python3.6/site-packages/distributed/utils.py 在getitem(self,key)1517 defgetitem(self,key)中: ->1518 value=super()

~/.edm/envs/evaxi3.6/lib/python3.6/collections/init.py in getitem(self,key) 990返回self.缺失(self,键) -->991升起钥匙错误(钥匙) 992 def设置项(self,key,item):self.data[key]=项

KeyError:0x11ffc50d0处的函数zippy

在处理上述异常期间,发生了另一个异常:

ValueError回溯(最近的调用 最后) ~/.edm/envs/evaxi3.6/lib/python3.6/site-packages/distributed/protocol/pickle.py 在转储中(x) 40如果结果中有b“main”: --->41返回cloudpickle.dumps(x,协议=pickle.HIGHEST\u协议) 42.其他:

~/.edm/envs/evaxi3.6/lib/python3.6/site-packages/cloudpickle/cloudpickle.py 在转储中(obj,协议)1147 cp=CloudPickler(文件, 协议=协议) ->1148 cp.dump(obj)1149返回文件.getvalue()

~/.edm/envs/evaxi3.6/lib/python3.6/site-packages/cloudpickle/cloudpickle.py 在转储中(自,obj) 490试试: -->491回料酸洗机卸料(自、obj) 492除运行时错误为e外:

转储中的~/.edm/envs/evaxi3.6/lib/python3.6/pickle.py(self,obj) 408 self.framer.start_framing() -->409自我保存(obj) 410自写(停止)

保存中的~/.edm/envs/evaxi3.6/lib/python3.6/pickle.py(self,obj, 保存\u持久\u id) 475如果f不是无: -->476 f(self,obj)#用显式self调用未绑定方法 477返回

~/.edm/envs/evaxi3.6/lib/python3.6/site-packages/cloudpickle/cloudpickle.py 保存功能中(自身、对象、名称) 565其他: -->566返回自我保存函数元组(obj) 567

~/.edm/envs/evaxi3.6/lib/python3.6/site-packages/cloudpickle/cloudpickle.py 保存函数中的元组(self,func) 779状态['kwdefaults']=func.kwdefaults -->780保存(状态) 781写入(pickle.TUPLE)

保存中的~/.edm/envs/evaxi3.6/lib/python3.6/pickle.py(self,obj, 保存\u持久\u id) 475如果f不是无: -->476 f(self,obj)#用显式self调用未绑定方法 477返回

保存目录中的~/.edm/envs/evaxi3.6/lib/python3.6/pickle.py(self,obj) 820自我记忆(obj) -->821自身批处理设置项(obj.items()) 822

批次设置项中的~/.edm/envs/evaxi3.6/lib/python3.6/pickle.py(自, (项目) 846保存(k) -->847保存(v) 848写入(设置项)

保存中的~/.edm/envs/evaxi3.6/lib/python3.6/pickle.py(self,obj, 保存\u持久\u id) 475如果f不是无: -->476 f(self,obj)#用显式self调用未绑定方法 477返回

保存目录中的~/.edm/envs/evaxi3.6/lib/python3.6/pickle.py(self,obj) 820自我记忆(obj) -->821自身批处理设置项(obj.items()) 822

批次设置项中的~/.edm/envs/evaxi3.6/lib/python3.6/pickle.py(自, (项目) 851保存(k) -->852保存(v) 853写入(设置项)

保存中的~/.edm/envs/evaxi3.6/lib/python3.6/pickle.py(self,obj, 保存\u持久\u id) 495如果reduce不是None: -->496 rv=减少(自编程) 497其他:

ValueError:无法pickle包含指针的ctypes对象

不幸的是,我仍然不理解错误!我刚刚开始学习
dask
,对
ctypes
只有一些基本的经验。有没有人对如何解决这一问题提出建议,甚至了解需要解决的问题


谢谢

实际上,您不能序列化引用闭包或参数中的C函数的函数。但是,如果您的函数位于一个所有工作人员都可以访问的模块中,那么您最终只能序列化模块名,python做了正确的事情

模块zippy.py(python路径上的某个地方,可能是示例的当前目录):

主脚本:

from dask.distributed import Client
import zippy
if __name__ == "__main__":
    # if running as a script, this is helpful
    client = Client(n_workers = 4)

result = dask.delayed(zippy.zippy)(1., 2.)
result.compute()
如果不想创建模块,另一种解决方案是在函数中执行所有C导入和定义

def zippy(x, y):
    _mod = ctypes.cdll.LoadLibrary(os.path.join(current_dir, "zippy.so"))

    _zippy_sum = _mod.zippy_sum
    _zippy_sum.argtypes = [ctypes.c_double, ctypes.c_double]
    _zippy_sum.restype = ctypes.c_double

    z = _zippy_sum(x, y)

    return z

实际上,您不能序列化在闭包或参数中引用C函数的函数。但是,如果您的函数位于一个所有工作人员都可以访问的模块中,那么您最终只能序列化模块名,python做了正确的事情

模块zippy.py(python路径上的某个地方,可能是examp的当前目录
def zippy(x, y):
    _mod = ctypes.cdll.LoadLibrary(os.path.join(current_dir, "zippy.so"))

    _zippy_sum = _mod.zippy_sum
    _zippy_sum.argtypes = [ctypes.c_double, ctypes.c_double]
    _zippy_sum.restype = ctypes.c_double

    z = _zippy_sum(x, y)

    return z