PyCUDA程序性能测量

我们可以使用Python时间测量选项来测量CUDA程序的性能,但结果不会完全精准,因为它包含操作系统中线程延迟的时间开销、操作系统中的调度等诸多因素。使用CPU测量的时间也将取决于CPU高精度计时器的可用性,很多时候主机在GPU内核运行时执行异步计算,因此Python 的CPU计时器可能无法为内核执行提供正确的时间。为了测量GPU内核计算的时间,PyCUDA提供了一个事件API。
CUDA事件是在PyCUDA程序的指定点记录的GPU时间戳。在这个API中,GPU记录时间戳,免除使用CPU计时器测量性能时出现的问题。使用CUDA事件测量时间需要两个步骤:创建事件和记录事件。我们可以记录两个事件:一个在代码的开头,一个在代码的结尾。然后将尝试计算两个事件之间的时间差,这两个事件将为我们的代码提供总体
性能。

import pycuda.autoinit
import pycuda.driver as drv
import numpy
import time
import math
N = 1000000

from pycuda.compiler import SourceModule
mod = SourceModule("""
                   
__global__ void add_num(float *d_result, float *d_a, float *d_b,int N)
{
 int tid = threadIdx.x + blockIdx.x * blockDim.x;	
	while (tid < N)
    {
 d_result[tid] = d_a[tid] + d_b[tid];
 tid = tid + blockDim.x * gridDim.x;
}
    }
""")
start = drv.Event()
end=drv.Event()
add_num = mod.get_function("add_num")

h_a = numpy.random.randn(N).astype(numpy.float32)
h_b = numpy.random.randn(N).astype(numpy.float32)

h_result = numpy.zeros_like(h_a)
h_result1 = numpy.zeros_like(h_a)
n_blocks = math.ceil((N/1024) +1)
start.record()
add_num(drv.Out(h_result), drv.In(h_a), drv.In(h_b),numpy.uint32(N),
        block=(1024,1,1), grid=(n_blocks,1))
end.record()
end.synchronize()
secs = start.time_till(end)*1e-3
print("Addition of %d element of GPU"%N)
print("%fs" % (secs))
start = time.time()
for i in range(0,N):
    h_result1[i] = h_a[i] +h_b[i]
end = time.time()
print("Addition of %d element of CPU"%N)
print(end-start,"s")

由于元素的数量很多,将启动多个线程块和线程,线程ID和块ID都用于计算线程索引。如果启动的线程总数不等于元素总数,则同一线程将执行多个元素相加。这由内核函数内部的while循环完成,它还将确保线程索引不会超出数组元素。除了输入数组和输出数组之外,数组的大小也作为内核函数的参数,因为在SourceModule中内核代码无法访问Python全局变量。
创建start和 end两个事件来测量GPU代码的计时,driver类中的Event()函数用于定义事件对象,然后使用get_function创建指向内核函数的指针引用。使用numpy库的randn函数用随机数初始化两个具有1 000 000个元素的数组,生成浮点数从而转换为单精度数字,以加快设备上的计算速度。
每个线程块支持1024个线程,正如我们在设备属性部分看到的那样。基于这个条件,线程块总数用N除以1024来计算,结果可能是一个浮点值。使用numpy库的ceil 函数将其转换为下一个最高的整数值,然后启动内核,计算出线程块和每个块1024个线程数。数组的大小以numpy.uint32数据类型传递。
使用record 函数记录调用内核函数前后的时间,并计算时间差得出内核函数的时间,打印在控制台上。用Python的 time库来测量CPU时间,for循环来遍历数组中的每个元素。(注意:也可以用h_result1=h_a+h_b,因为这两个都是numpy数组。)使用time.time()函数在for循环前后测量时间,这两个时间之间的差异将打印在控制台上。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

给算法爸爸上香

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值