【发布时间】:2020-05-26 09:05:12
【问题描述】:
我在让它正常工作时遇到了一些问题,我也愿意接受其他建议,因为我不能 100% 确定我是否走对了这条路。
这是一些简单的虚拟数据:
times = pd.date_range(start='2012-01-01',freq='1W',periods=25)
x = np.array([range(0,20)]).squeeze()
y = np.array([range(20,40)]).squeeze()
data = np.random.randint(3, size=(25,20,20))
ds = xr.DataArray(data, dims=['time', 'y', 'x'], coords = {'time': times, 'y': y, 'x': x})
对于每个 x,y 坐标,我想随时间返回最长的 1 或 2 序列。所以我的输入数组是 3D(时间,x,y),我的输出是 2D(x,y)。 'seq_gufunc' 中的代码受到this thread 的启发。 我的实际数据集要大得多(使用土地利用类而不是 1s、2s 等),这只是更大工作流程的一小部分,我还使用 dask 进行并行处理。所以最后这应该快速有效地运行,这就是为什么我最终试图弄清楚如何让 numba 的 @guvectorize 和 Xarray 的 apply_ufunc 一起工作:
@guvectorize(
"(int64[:], int64[:])",
"(n) -> (n)", target='parallel', nopython=True
)
def seq_gufunc(x, out):
f_arr = np.array([False])
bool_stack = np.hstack((f_arr, (x == 1) | (x == 2), f_arr))
# Get start, stop index pairs for sequences
idx_pairs = np.where(np.diff(bool_stack))[0].reshape(-1, 2)
# Get length of longest sequence
longest_seq = np.max(np.diff(idx_pairs))
out[:] = longest_seq
## Input for dim would be: 'time'
def apply_seq_gufunc(data, dim):
return xr.apply_ufunc(seq_gufunc,
data,
input_core_dims=[[dim]],
exclude_dims=set((dim,)),
dask="allowed")
可能存在一些非常明显的错误,希望有人能指出。我很难理解后台实际发生了什么,以及我应该如何设置 @guvectorize 的布局字符串和 apply_ufunc 的参数,以便它做我想要的。
编辑2:
这是有效的解决方案。有关apply_ufunc 和guvectorize 的参数的更多信息,请参阅@OriolAbril 的答案。还必须实现 if...else... 子句,以防没有匹配的值,并避免引发 ValueError 。
@guvectorize(
"(int64[:], int64[:])",
"(n) -> ()", nopython=True
)
def seq_gufunc(x, out):
f_arr = np.array([False])
bool_stack = np.hstack((f_arr, (x == 1) | (x == 2), f_arr))
if np.sum(bool_stack) == 0:
longest_seq = 0
else:
# Get start, stop index pairs for sequences
idx_pairs = np.where(np.diff(bool_stack))[0].reshape(-1, 2)
# Get length of longest sequence
longest_seq = np.max(np.diff(idx_pairs))
out[:] = longest_seq
def apply_seq_gufunc(data, dim):
return xr.apply_ufunc(seq_gufunc,
data,
input_core_dims=[[dim]],
dask="parallelized",
output_dtypes=['uint8']
)
【问题讨论】:
-
不能解决问题,但可能对您来说仍然很有趣:
guvectorize不能与dask.Client一起使用,以防您打算使用集群左右。至少它没有(不确定他们是否适应了它 - 我需要在某个地方搜索关于它的对话) -
嗨,瓦尔!我已经实现了另一个
@guvectorize函数,最初通过dask.Client使用本地集群,直到发生一些随机段错误。现在我使用.compute(scheduler='single-threaded')作为临时解决方案,似乎(?)可以工作。但很高兴知道究竟是什么导致了这些段错误。有一阵子我发疯了。 -
是的,我花了一整天的时间在谷歌上搜索可能出了什么问题,直到我在某个地方找到了一个小对话,
guvectorize函数不能传递给调度程序和工作人员......我希望我记得这个线程在哪里,也许它会回到我的脑海中。无论如何,在一台机器上使用dask可以正常工作,但你会坚持下去。
标签: python numpy numba python-xarray numpy-ufunc