3.13。 CUDA Ufuncs 和广义 Ufuncs

原文: http://numba.pydata.org/numba-doc/latest/cuda/ufunc.html

此页面描述了类似 CUDA ufunc 的对象。

为了支持 CUDA 程序的编程模式,CUDA Vectorize 和 GUVectorize 不能生成传统的 ufunc。相反,返回类似 ufunc 的对象。此对象是一个非常模拟但与常规 NumPy ufunc 不完全兼容的对象。 CUDA ufunc 增加了对传递设备内阵列(已在 GPU 设备上)的支持,以减少 PCI-express 总线上的流量。它还接受<cite>流</cite>关键字以在异步模式下启动。

3.13.1。示例:基本示例

  1. import math
  2. from numba import vectorize, cuda
  3. import numpy as np
  4. @vectorize(['float32(float32, float32, float32)',
  5. 'float64(float64, float64, float64)'],
  6. target='cuda')
  7. def cu_discriminant(a, b, c):
  8. return math.sqrt(b ** 2 - 4 * a * c)
  9. N = 10000
  10. dtype = np.float32
  11. # prepare the input
  12. A = np.array(np.random.sample(N), dtype=dtype)
  13. B = np.array(np.random.sample(N) + 10, dtype=dtype)
  14. C = np.array(np.random.sample(N), dtype=dtype)
  15. D = cu_discriminant(A, B, C)
  16. print(D) # print result

3.13.2。示例:调用设备功能

所有 CUDA ufunc 内核都能够调用其他 CUDA 设备功能:

  1. from numba import vectorize, cuda
  2. # define a device function
  3. @cuda.jit('float32(float32, float32, float32)', device=True, inline=True)
  4. def cu_device_fn(x, y, z):
  5. return x ** y / z
  6. # define a ufunc that calls our device function
  7. @vectorize(['float32(float32, float32, float32)'], target='cuda')
  8. def cu_ufunc(x, y, z):
  9. return cu_device_fn(x, y, z)

3.13.3。广义 CUDA ufuncs

可以使用 CUDA 在 GPU 上执行通用 ufunc,类似于 CUDA ufunc 功能。这可以通过以下方式完成:

  1. from numba import guvectorize
  2. @guvectorize(['void(float32[:,:], float32[:,:], float32[:,:])'],
  3. '(m,n),(n,p)->(m,p)', target='cuda')
  4. def matmulcore(A, B, C):
  5. ...

有时候 gufunc 内核会使用太多的 GPU 资源,这会导致内核启动失败。用户可以通过在已编译的 gufunc 对象上设置 <cite>max_blocksize</cite> 属性来显式控制线程块的最大大小。

  1. from numba import guvectorize
  2. @guvectorize(..., target='cuda')
  3. def very_complex_kernel(A, B, C):
  4. ...
  5. very_complex_kernel.max_blocksize = 32 # limits to 32 threads per block