所有这些代码都可以在pandas中使用,但是运行单线程很慢。
我有一个创建缓慢的对象(这是一个bloom过滤器)。
我有类似下面的代码:
def has_match(row, my_filter):
return my_filter.matches(
a=row.a, b =row.b
)
# ....make dask dataframe ddf
ddf['match'] = ddf.apply(has_match, args=(my_filter, ), axis=1, meta=(bool))
ddf.compute()
当我尝试运行此程序时,我收到一个开始的错误:
distributed.protocol.core - CRITICAL - Failed to Serialize
我的对象是从C库创建的,因此它不能自动进行序列化并不令我感到惊讶,但我不知道如何解决此问题。
答案 0 :(得分:0)
一种方法是完全避免该问题,并且根本不使用单独的进程。这样,您将不需要在它们之间序列化数据。
ddf.compute(scheduler='threads')
但这确实限制了您只能在一台计算机上的单个进程中运行,这可能不是您想要的。
如果您能弄清楚如何将对象转换为字节串,则可以在对象上实现pickle协议(例如__getstate__
和__setstate__
方法,请参见Python文档)或您可以将定义添加到dask_serialize和dask_deserialize可调度函数。有关示例,请参见Dask's serialization docs。
也许很难序列化对象,但是每个分区重新创建一次便宜吗?
def has_match(partition):
my_filter = make_filter(...)
return partition.apply(my_filter.matches(a=row.a, b =row.b))
ddf['match'] = ddf.map_partitions(has_match)
答案 1 :(得分:0)
Distributed希望所有中间结果都可序列化。就您而言,您有一个没有实现泡菜的对象。通常,您可以在此处选择几种方法(按最佳到最差的恕我直言):
为此对象执行泡菜。请注意,使用copyreg模块可以为您不在控件中的类添加pickle支持。
在函数中手动缓存过滤器的创建。您可以使用对象或模块中的全局变量来执行此操作。请注意,下面的这段代码需要成为导入模块的一部分,而不是您的交互式会话的一部分(即不在jupyter notebook / ipython会话中)。
例如(未试用):
myfilter = None
def get_or_load():
global myfilter
if myfilter is None:
myfilter = load_filter()
else:
return myfilter
def load_filter():
pass
def has_match(row):
my_filter = get_or_load()
return my_filter.matches(a=row.a, b=row.b)
然后在您的用户代码中:
from my_filter_utils import has_match
ddf['match'] = ddf.apply(has_match, axis=1, meta=('matches', bool))
例如(未试用):
from dask import delayed
class Wrapper(object):
def __init__(self, func):
self.func = func
self.filter = func()
def __reduce__(self):
# When unpickled, the filter will be reloaded
return (Wrapper, (func,))
def load_filter():
pass
# Create a delayed function to load the filter
wrapper = delayed(Wrapper)(load_filter)
# Optionally persist the wrapper in the cluster, to be reused over multiple computations
wrapper = wrapper.persist()
def has_match(row, wrapper):
return wrapper.filter.matches(a=row.a, b=row.b)
ddf['match'] = ddf.apply(has_match, args=(wrapper,), axis=1, meta=('matches', bool))