gpt4 book ai didi

python-3.x - 为什么numba cuda调用几次后运行速度变慢?

转载 作者:行者123 更新时间:2023-12-02 18:46:48 25 4
gpt4 key购买 nike

我正在尝试如何在 numba 中使用 cuda。然而我却遇到了与我预想不同的事情。这是我的代码

from numba import cuda
@cuda.jit
def matmul(A, B, C):
"""Perform square matrix multiplication of C = A * B
"""
d=cuda.local.array((3,3),dtype=numba.float64)
i, j = cuda.grid(2)
if i < C.shape[0] and j < C.shape[1]:
tmp = 0.
for k in range(A.shape[1]):
tmp += A[i, k] * B[k, j]
C[i, j] = tmp

这是我自己定义的矩阵函数,用于使用numba.cuda进行测试。在运行测试之前,我还在以下代码中加载了数组:

import numpy as np
a=np.random.rand(2000,2000)
b=np.random.rand(2000,2000)
c=np.empty((2000,2000))
a1=cuda.to_device(a)
b1=cuda.to_device(b)
c1=cuda.to_device(c)

然后我使用了以下代码进行实验:

from time import time
count =0
start=time()
for i in range(2000):
matmul[(256,256),(16,16)](a1,b1,c1)
count +=1
print(count)

前 1028 次运行中 for 循环运行得非常快。然而,在 1028 号之后,它运行得非常慢。到底是什么导致了这个问题,我该如何解决它。顺便说一句,我正在win10上运行。

这是我从 numba.cuda 调用的 cuda 信息

from numba import cuda
gpu = cuda.get_current_device()
print("name = %s" % gpu.name)
print("maxThreadsPerBlock = %s" % str(gpu.MAX_THREADS_PER_BLOCK))
print("maxBlockDimX = %s" % str(gpu.MAX_BLOCK_DIM_X))
print("maxBlockDimY = %s" % str(gpu.MAX_BLOCK_DIM_Y))
print("maxBlockDimZ = %s" % str(gpu.MAX_BLOCK_DIM_Z))
print("maxGridDimX = %s" % str(gpu.MAX_GRID_DIM_X))
print("maxGridDimY = %s" % str(gpu.MAX_GRID_DIM_Y))
print("maxGridDimZ = %s" % str(gpu.MAX_GRID_DIM_Z))
print("maxSharedMemoryPerBlock = %s" %
str(gpu.MAX_SHARED_MEMORY_PER_BLOCK))
print("asyncEngineCount = %s" % str(gpu.ASYNC_ENGINE_COUNT))
print("canMapHostMemory = %s" % str(gpu.CAN_MAP_HOST_MEMORY))
print("multiProcessorCount = %s" % str(gpu.MULTIPROCESSOR_COUNT))
print("warpSize = %s" % str(gpu.WARP_SIZE))
print("unifiedAddressing = %s" % str(gpu.UNIFIED_ADDRESSING))
print("pciBusID = %s" % str(gpu.PCI_BUS_ID))
print("pciDeviceID = %s" % str(gpu.PCI_DEVICE_ID))

输出是:

名称 = b'GeForce GTX 1050 Ti'

每个 block 的最大线程数 = 1024

maxBlockDimX = 1024

maxBlockDimY = 1024

最大块尺寸Z = 64

maxGridDimX = 2147483647

maxGridDimY = 65535

maxGridDimZ = 65535

每个 block 的最大共享内存 = 49152

asyncEngineCount = 2

canMapHostMemory = 1

多处理器计数 = 6

扭曲大小=32

统一寻址 = 1

pciBusID = 3

pciDeviceID = 0

最佳答案

这是由与 GPU 内核启动相关的异步启动队列引起的。

当你告诉 numba 提交 GPU 内核时:

matmul[(256,256),(16,16)](a1,b1,c1)

此请求进入队列,发出该内核调用的 CPU 线程(即 python)可以继续,即使 GPU 内核尚未完成或什至尚未启动。

CUDA 运行时将这些请求排队并在 GPU 准备好执行更多工作时发出它们。

在 for 循环快速递增期间,您最初看到的是队列填满了工作请求。这并不代表 GPU 执行工作所需的实际时间。

最终队列填满,CUDA 运行时在内核启动时暂停 CPU 线程(即 python),直到队列槽打开。此时,for 循环可以继续进行一次迭代。正是在这一点上(可能在 1028 次迭代左右),您开始看到“速度变慢”。此后,for 循环大约以 GPU 内核执行和从处理队列中删除的速率进行。

这里没有什么需要修复的;这是预期的行为。

如果您希望 for 循环仅按照 GPU 内核实际执行的速率进行,那么您应该在 for 循环中插入一个同步函数。

例如,numba 提供 numba.cuda.synchronize()因此,如果您按如下方式修改 for 循环:

for i in range(2000):
matmul[(256,256),(16,16)](a1,b1,c1)
cuda.synchronize()
count +=1
print(count)

您将看到 for 循环以 GPU 工作完成的实际速率进行,而不是“队列填充”速率。

关于python-3.x - 为什么numba cuda调用几次后运行速度变慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52263701/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com