广义 Ufuncs

NumPy 提供了 广义 ufuncs 的概念。广义 ufuncs 是区分传递数组的不同维度的函数,这些维度分为循环维度和核心维度两类。为了实现这一点,需要为 NumPy 广义 ufuncs 指定一个 签名

Dask 通过遵循相应的 ufunc 协议,集成了与 NumPy 广义 ufuncs 的互操作性,并提供了一个包装器,可以将 Python 函数变为广义 ufunc。

用法

NumPy 广义 Ufuncs

注意

NumPy 广义 ufuncs 目前(v1.14.3 及更早版本)存储在 np.linalg._umath_linalg 内部,未来可能会改变。

import dask.array as da
import numpy as np

x = da.random.default_rng().normal(size=(3, 10, 10), chunks=(2, 10, 10))

w, v = np.linalg._umath_linalg.eig(x, output_dtypes=(float, float))

创建广义 UFuncs

在不深入 CPython API 的情况下创建自己的 GUFuncs 可能比较困难。然而,Numba 项目通过其 numba.guvectorize 装饰器提供了一个很好的实现。更多信息请参阅 Numba 的文档

包装你自己的 Python 函数

gufunc 可用于使 Python 函数表现得像一个广义 ufunc

x = da.random.default_rng().normal(size=(10, 5), chunks=(2, 5))

def foo(x):
    return np.mean(x, axis=-1)

gufoo = da.gufunc(foo, signature="(i)->()", output_dtypes=float, vectorize=True)

y = gufoo(x)

除了 gufuncas_gufunc 装饰器也可以方便地使用

x = da.random.normal(size=(10, 5), chunks=(2, 5))

@da.as_gufunc(signature="(i)->()", output_dtypes=float, vectorize=True)
def gufoo(x):
    return np.mean(x, axis=-1)

y = gufoo(x)

免责声明

这个实验性的广义 ufunc 集成尚不完善

  • gufunc 不会创建一个真正的广义 ufunc 以用于 Dask 以外的其他输入数组。也就是说,目前,gufunc 会将所有输入参数转换为 dask.array.Array

  • 自动推断 output_dtypes 尚未实现

API

apply_gufunc(func, signature, *args[, axes, ...])

将广义 ufunc 或类似的 Python 函数应用于数组。

as_gufunc([signature])

dask.array.gufunc 的装饰器。

gufunc(pyfunc, *[, signature, vectorize, ...])

调用时将 pyfunc 绑定到 dask.array.apply_gufunc 中。