# 5.7。 ROC Ufuncs 和广义 Ufuncs
> 原文: [http://numba.pydata.org/numba-doc/latest/roc/ufunc.html](http://numba.pydata.org/numba-doc/latest/roc/ufunc.html)
此页面描述了类似 ROC ufunc 的对象。
为了支持 ROC 程序的编程模式,ROC Vectorize 和 GUVectorize 不能生成传统的 ufunc。相反,返回类似 ufunc 的对象。此对象是一个非常模拟但与常规 NumPy ufunc 不完全兼容的对象。 ROC ufunc 增加了对传递设备内阵列(已在 GPU 设备上)的支持,以减少 PCI-express 总线上的流量。它还接受<cite>流</cite>关键字以在异步模式下启动。
## 5.7.1。基本 ROC UFunc 示例
```py
import math
from numba import vectorize
import numpy as np
@vectorize(['float32(float32, float32, float32)',
'float64(float64, float64, float64)'],
target='roc')
def roc_discriminant(a, b, c):
return math.sqrt(b ** 2 - 4 * a * c)
N = 10000
dtype = np.float32
# prepare the input
A = np.array(np.random.sample(N), dtype=dtype)
B = np.array(np.random.sample(N) + 10, dtype=dtype)
C = np.array(np.random.sample(N), dtype=dtype)
D = roc_discriminant(A, B, C)
print(D) # print result
```
## 5.7.2。从 ROC UFuncs 调用设备功能
所有 ROC ufunc 内核都能够调用其他 ROC 设备函数:
```py
from numba import vectorize, roc
# define a device function
@roc.jit('float32(float32, float32, float32)', device=True)
def roc_device_fn(x, y, z):
return x ** y / z
# define a ufunc that calls our device function
@vectorize(['float32(float32, float32, float32)'], target='roc')
def roc_ufunc(x, y, z):
return roc_device_fn(x, y, z)
```
## 5.7.3。广义 ROC ufuncs
可以使用 ROC 在 GPU 上执行广义 ufunc,类似于 ROC ufunc 功能。这可以通过以下方式完成:
```py
from numba import guvectorize
@guvectorize(['void(float32[:,:], float32[:,:], float32[:,:])'],
'(m,n),(n,p)->(m,p)', target='roc')
def matmulcore(A, B, C):
...
```
也可以看看
[矩阵乘法示例](examples.html#roc-matmul)。
## 5.7.4。异步执行:一次一个块
将数据分区为块允许计算和内存传输重叠。这可以提高 ufunc 的吞吐量,并使您的 ufunc 能够处理大于 GPU 内存容量的数据。例如:
```py
import math
from numba import vectorize, roc
import numpy as np
# the ufunc kernel
def discriminant(a, b, c):
return math.sqrt(b ** 2 - 4 * a * c)
roc_discriminant = vectorize(['float32(float32, float32, float32)'],
target='roc')(discriminant)
N = int(1e+8)
dtype = np.float32
# prepare the input
A = np.array(np.random.sample(N), dtype=dtype)
B = np.array(np.random.sample(N) + 10, dtype=dtype)
C = np.array(np.random.sample(N), dtype=dtype)
D = np.zeros(A.shape, dtype=A.dtype)
# create a ROC stream
stream = roc.stream()
chunksize = 1e+6
chunkcount = N // chunksize
# partition numpy arrays into chunks
# no copying is performed
sA = np.split(A, chunkcount)
sB = np.split(B, chunkcount)
sC = np.split(C, chunkcount)
sD = np.split(D, chunkcount)
device_ptrs = []
# helper function, async requires operation on coarsegrain memory regions
def async_array(arr):
coarse_arr = roc.coarsegrain_array(shape=arr.shape, dtype=arr.dtype)
coarse_arr[:] = arr
return coarse_arr
with stream.auto_synchronize():
# every operation in this context with be launched asynchronously
# by using the ROC stream
dchunks = [] # holds the result chunks
# for each chunk
for a, b, c, d in zip(sA, sB, sC, sD):
# create coarse grain arrays
asyncA = async_array(a)
asyncB = async_array(b)
asyncC = async_array(c)
asyncD = async_array(d)
# transfer to device
dA = roc.to_device(asyncA, stream=stream)
dB = roc.to_device(asyncB, stream=stream)
dC = roc.to_device(asyncC, stream=stream)
dD = roc.to_device(asyncD, stream=stream, copy=False) # no copying
# launch kernel
roc_discriminant(dA, dB, dC, out=dD, stream=stream)
# retrieve result
dD.copy_to_host(asyncD, stream=stream)
# store device pointers to prevent them from freeing before
# the kernel is scheduled
device_ptrs.extend([dA, dB, dC, dD])
# store result reference
dchunks.append(asyncD)
# put result chunks into the output array 'D'
for i, result in enumerate(dchunks):
sD[i][:] = result[:]
# data is ready at this point inside D
print(D)
```
- 1. 用户手册
- 1.1。 Numba 的约 5 分钟指南
- 1.2。概述
- 1.3。安装
- 1.4。使用@jit 编译 Python 代码
- 1.5。使用@generated_jit 进行灵活的专业化
- 1.6。创建 Numpy 通用函数
- 1.7。用@jitclass 编译 python 类
- 1.8。使用@cfunc 创建 C 回调
- 1.9。提前编译代码
- 1.10。使用@jit 自动并行化
- 1.11。使用@stencil装饰器
- 1.12。从 JIT 代码 中回调到 Python 解释器
- 1.13。性能提示
- 1.14。线程层
- 1.15。故障排除和提示
- 1.16。常见问题
- 1.17。示例
- 1.18。会谈和教程
- 2. 参考手册
- 2.1。类型和签名
- 2.2。即时编译
- 2.3。提前编译
- 2.4。公用事业
- 2.5。环境变量
- 2.6。支持的 Python 功能
- 2.7。支持的 NumPy 功能
- 2.8。与 Python 语义的偏差
- 2.9。浮点陷阱
- 2.10。 Python 2.7 寿命终止计划
- 3. 用于 CUDA GPU 的 Numba
- 3.1。概述
- 3.2。编写 CUDA 内核
- 3.3。内存管理
- 3.4。编写设备功能
- 3.5。 CUDA Python 中支持的 Python 功能
- 3.6。支持的原子操作
- 3.7。随机数生成
- 3.8。设备管理
- 3.10。示例
- 3.11。使用 CUDA 模拟器 调试 CUDA Python
- 3.12。 GPU 减少
- 3.13。 CUDA Ufuncs 和广义 Ufuncs
- 3.14。共享 CUDA 内存
- 3.15。 CUDA 阵列接口
- 3.16。 CUDA 常见问题
- 4. CUDA Python 参考
- 4.1。 CUDA 主机 API
- 4.2。 CUDA 内核 API
- 4.3。内存管理
- 5. 用于 AMD ROC GPU 的 Numba
- 5.1。概述
- 5.2。编写 HSA 内核
- 5.3。内存管理
- 5.4。编写设备功能
- 5.5。支持的原子操作
- 5.6。代理商
- 5.7。 ROC Ufuncs 和广义 Ufuncs
- 5.8。示例
- 6. 扩展 Numba
- 6.1。高级扩展 API
- 6.2。低级扩展 API
- 6.3。示例:间隔类型
- 7. 开发者手册
- 7.1。贡献给 Numba
- 7.2。 Numba 建筑
- 7.3。多态调度
- 7.4。关于发电机的注意事项
- 7.5。关于 Numba Runtime 的注意事项
- 7.6。使用 Numba Rewrite Pass 获得乐趣和优化
- 7.7。实时变量分析
- 7.8。上市
- 7.9。模板注释
- 7.10。关于自定义管道的注意事项
- 7.11。环境对象
- 7.12。哈希 的注意事项
- 7.13。 Numba 项目路线图
- 8. Numba 增强建议
- 9. 术语表