高端网站设计有哪些,谁给推荐一个免费的好网站,西安做网站程序,文本文档做网站怎么加图片上周使用GPU加速了一个算法#xff0c;效果特别惊艳#xff0c;由于算法代码本身没有太大参考价值#xff0c;所以这里只记录了一些心得体会#xff0c;以便后续遇到问题进行参考排查
numba加速代码编写注意事项
numba加速代码编写一定要注意#xff1a; 1、开辟空间效果特别惊艳由于算法代码本身没有太大参考价值所以这里只记录了一些心得体会以便后续遇到问题进行参考排查
numba加速代码编写注意事项
numba加速代码编写一定要注意 1、开辟空间里面所有计算操作要返回的值需要开辟空间 2、ID号搞清楚要用一维矩阵进行计算还是二维矩阵进行计算一维矩阵计算需搞清楚最关键的ID号对应的线程号二维矩阵则要搞清楚两个ID分别对应的实际意义 3、在进行GPU内部的函数中numpy的一些操作是不支持的尽量在外部定义好或者搞清楚numpy函数的实际意义然后用最原始的代码写出来在CPU上测试等价然后放到GPU中进行测试这样避免运行时候出错却找不到原因 4、在GPU运行的函数中返回的结果变量尽量不要使用切片包装传入如果要用切片包装可以把变量及整体线程ID号带入实际函数内部。先测试直接输出或改写内部变量值再输出看看能否正确输出如果不能正确输出则是否ID搞错了。我上周写的代码中这里坑住我了
如果运行出错不要慌一般会有提示根据提示想想原因或者采用注释法排查问题一句句代码保留出来进行测试运行总能找到根本原因及解决办法
GPU加速效果太惊艳了编写过程也是很恼火但看到了最终成果中间编写的恼火过程可以忽略不计。
贴一个Demo程序,方便了解一般编写规则
一维矩阵GPU计算 from numba import cuda
import numpy as np
import math
from time import time# # 定义一个简单的设备函数
# cuda.jit(deviceTrue)
# def square(x):
# return x * x# 定义一个简单的设备函数
cuda.jit(deviceTrue)
def add(a,b):return abcuda.jit
def gpu_add(a, b, result, n):idx cuda.threadIdx.x cuda.blockDim.x * cuda.blockIdx.xif idx n :result[idx] add(a[idx] , b[idx])# result[idx] a[idx] b[idx]def main():n 20000000x np.arange(n).astype(np.int32)y 2 * x# 拷贝数据到设备端x_device cuda.to_device(x)y_device cuda.to_device(y)# 在显卡设备上初始化一块用于存放GPU计算结果的空间gpu_result cuda.device_array(n)cpu_result np.empty(n)threads_per_block 1024blocks_per_grid math.ceil(n / threads_per_block)start time()gpu_add[blocks_per_grid, threads_per_block](x_device, y_device, gpu_result, n)cuda.synchronize()print(gpu vector add time str(time() - start))start time()cpu_result np.add(x, y)print(cpu vector add time str(time() - start))if (np.array_equal(cpu_result, gpu_result.copy_to_host())):print(result correct!)if __name__ __main__:main()二维矩阵GPU计算 import numpy as np
from numba import cuda# 使用Numba的cuda.jit装饰器来编写CUDA加速的函数
cuda.jit
def multiply_array(arr, result):i, j cuda.grid(2)if i arr.shape[0] and j arr.shape[1]:result[i, j] arr[i, j] * 2 # 将数组中的每个元素乘以2# 生成一个随机的二维数组
arr np.random.rand(3, 3)# 将数据传入设备中
d_arr cuda.to_device(arr)# 创建一个与输入数组形状相同的结果数组
result np.empty_like(arr)# 将结果数组传入设备中
d_result cuda.to_device(result)# 定义线程块和线程网格的大小
threads_per_block (16, 16)
blocks_per_grid_x (arr.shape[0] threads_per_block[0] - 1) // threads_per_block[0]
blocks_per_grid_y (arr.shape[1] threads_per_block[1] - 1) // threads_per_block[1]
blocks_per_grid (blocks_per_grid_x, blocks_per_grid_y)# 在设备上执行加速计算
multiply_array[blocks_per_grid, threads_per_block](d_arr, d_result)# 将结果拷贝回本地
d_result.copy_to_host(result)print(Original array:)
print(arr)
print(Result array:)
print(result)
记录一个调试错误如下图 “AttributeError: ‘list’ object has no attribute ‘squeeze’” 该错误是说list没有’squeeze’方法仔细检查GPU核函数好像没有调用’squeeze’方法经过调查发现传入GPU设备的代码是list将初始化方法list变为numpy即可猜想GPU计算的时候会自动调numpy的’squeeze’方法
更改前
linearSuccess [0]* AllNumber # 初始化CPU变量
d_linearSuccess cuda.to_device(linearSuccess)#变量传入GPU设备
...
更改后 linearSuccess np.zeros([AllNumber]) # 初始化CPU变量
d_linearSuccess cuda.to_device(linearSuccess)#变量传入GPU设备
...