如何使用Numba CUDA JIT装饰器?

问题描述 投票:0回答:1

我已按照本教程使用 Numba CUDA JIT 装饰器:https://www.youtube.com/watch?v=-lcWV4wkHsk&t=510s

这是我的Python代码:

import numpy as np
from timeit import default_timer as timer
from numba import cuda, jit

# This function will run on a CPU
def fill_array_with_cpu(a):
      for k in range(100000000):
            a[k] += 1

# This function will run on a CPU with @jit
@jit
def fill_array_with_cpu_jit(a):
      for k in range(100000000):
            a[k] += 1         

# This function will run on a GPU
@jit(target_backend='cuda')
def fill_array_with_gpu(a):
      for k in range(100000000):
            a[k] += 1   

# Main
a = np.ones(100000000, dtype = np.float64)

for i in range(3):
      start = timer()
      fill_array_with_cpu(a)
      print("On a CPU:", timer() - start)

for i in range(3):
      start = timer()
      fill_array_with_cpu_jit(a)
      print("On a CPU with @jit:", timer() - start)

for i in range(3):
      start = timer()
      fill_array_with_gpu(a)
      print("On a GPU:", timer() - start)

这是提示输出:

On a CPU: 24.228116830999852
On a CPU: 24.90354355699992
On a CPU: 24.277727688999903
On a CPU with @jit: 0.2590671719999591
On a CPU with @jit: 0.09131158500008496
On a CPU with @jit: 0.09054700799993043
On a GPU: 0.13547917200003212
On a GPU: 0.0922475330000907
On a GPU: 0.08995077999998102

使用

@jit
装饰器大大提高了处理速度。然而,我不清楚
@jit(target_backend='cuda')
装饰器是否允许该函数在 GPU 上处理。处理时间与
@jit
的功能类似。我想
@jit(target_backend='cuda')
不使用 GPU。事实上,我已经在没有 NVIDIA GPU 的机器上尝试过这段代码,并且得到了相同的结果,没有任何警告或错误。

如何让它在我的GPU上运行?我有一块 GeForce GT 730M。

python gpu numba
1个回答
0
投票

不存在

target_backend='cuda'
这样的事情。代码的所有功能都在 CPU 上执行(因此,一旦丢弃编译时间,计时相同)。 AFAIK 很久以前就有这样的选择,但现在没有了。由于多种原因,视频中的基准实际上并不正确,我认为它不应该被信任。


不仅视频中的基准不再正确,而且完成时也存在偏差。事实上,即使它存在并且按照我们希望的方式工作,它也不会高效,因为目标数组存储在主机内存中(通常在 RAM 中)。因此,数组必须传输到 GPU 设备内存,在设备上进行计算,然后然后从设备传输回到主机内存。问题是这样的数据传输非常昂贵(并且不能比主机内存更快)。此外,计算成本如此之低,以至于 CPU 计算应该是“内存限制”的,尽管一个核心可能不足以使 RAM 带宽饱和。在大多数平台上,需要使用“并行 CPU 实现”来使 RAM 完全饱和。这也可以更好地比较并行 CPU 实现与 GPU 实现,因为后者本质上是并行的。因此,所提供的基准充其量只是“有偏见”。最后,GPU 实现不可能更快,因为数据传输不可能比并行 CPU 实现更快,因为两者都受到主机 RAM 的限制。事实上,GPU 实现应该更慢,因为 CPU-GPU 互连(通常是 PCIe)通常无法达到与主机 RAM 带宽一样大的吞吐量。 最后但并非最不重要的一点是,该数组的类型为 float64,并且所有

客户端主流 Nvidia GPU 都不是为此而设计的

:它们执行此类 64 位浮点 (FP) 计算的速度非常慢。事实上,它们的速度非常慢,以至于主流 CPU 可以更快地进行计算。例如,您的 GT 730M GPU(低端非常旧的 Kepler GPU)在 32 位 FP 中可以达到 552 GFlops,而在 64 位 FP 中只能达到 23 GFlops。相比之下,同年发布的i5-4258U移动CPU可以达到92 GFlops。这是4倍多!如果您想在带有 CUDA 的 GPU 上进行快速 64 位 FP 计算,那么您需要一个原生支持 64 位 FP 计算的服务器端 Nvidia GPU(大多数都支持它们)。请注意,此类 GPU 的价格要昂贵得多。

请注意,第一次调用 Numba 函数包括
编译时间。这种开销必须在基准测试中被丢弃(通过急切地预编译函数,或者缓存它,或者只是丢弃第一次调用的时间)。

简而言之,这是一个糟糕的教程,您的 GPU 肯定无法比 CPU 更快地计算此特定操作。我建议您

阅读 Numba 的文档,它更加可靠

并且
是最新的

。您还可以阅读 CUDA 编程手册 了解更多信息,并阅读 此维基百科页面 了解有关 GPU 的信息。

© www.soinside.com 2019 - 2024. All rights reserved.