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