Pycuda

前言

以下参考及本文许多地方都有错误,指出立马修改
参考1
参考2
参考3

step01

安装pycuda库
缺少cuda,然后去必应上找的cuda 10.0
然后缺少一个编译用的cl.exe,去下载Microsoft Visual Studio/2017,一定不能是最新的
最后配置一下cl.exe的环境变量,跑起来一个基础的程序就可以了

from time import *
import numpy as np
from pycuda import gpuarray
import pycuda.autoinit
import os
import pycuda.driver as drv
from pycuda.compiler import SourceModule

# 刚开始这里不加会报错,就加上了
_path = r"C:/Program Files (x86)/Microsoft Visual Studio/2017/Enterprise/VC/Tools/MSVC/14.16.27023/bin/Hostx64/x64"
if os.system("cl.exe"):
   os.environ['PATH'] += ';' + _path
if os.system("cl.exe"):
   raise RuntimeError("cl.exe still not found, path probably incorrect")

def simple_speed_test():
    host_data = np.float32(np.random.random(50000000))

    t1 = time()
    host_data_2x =  host_data * np.float32(2)
    t2 = time()
    print(f'total time to compute on CPU: {t2 - t1}')

    device_data = gpuarray.to_gpu(host_data)

    t1 = time()
    device_data_2x =  device_data * np.float32(2)
    t2 = time()

    from_device = device_data_2x.get()

    print(f'total time to compute on GPU: {t2 - t1}')
    print(f'Is the host computation the same as the GPU computation? : {np.allclose(from_device, host_data_2x)}')

simple_speed_test()

step02

学习CUDA C编程,个人感觉比较重要的一点是索引选取和block以及thread的设计
自带的两个核:
在这里插入图片描述
在这里插入图片描述
还有一个用于自定义的SourceModel
在这里插入图片描述

# 编写核函数
mod = SourceModule("""
	__global__ void CAL_RMS(float *a ,float *b)
		{
	    int idx = threadIdx.x + blockIdx.x*blockDim.x;
	    a[idx] = (a[idx]-b[idx])*(a[idx]-b[idx])*96.04;
		}
	""")    
# 创建数据
acc_data = np.array(acc_data, dtype=np.float32)
acc_mean = np.empty_like(acc_data)
acc_mean[:] = np.float32(acc_data.mean())
# 分配内存
a_gpu = cuda.mem_alloc(acc_data.nbytes)
b_gpu = cuda.mem_alloc(acc_mean.nbytes)
# 赋值
cuda.memcpy_htod(a_gpu, acc_data)
cuda.memcpy_htod(b_gpu, acc_mean)
# 调用
func = mod.get_function("CAL_RMS")
func(a_gpu, b_gpu, grid=(int(acc_data.shape[0]/250),), block=(250, 1, 1))
# 取结果值
a_doubled = np.empty_like(acc_data)
cuda.memcpy_dtoh(a_doubled, a_gpu)

这里就涉及到一个很重要的概念,就是
int idx = threadIdx.x + blockIdx.x*blockDim.x;
pycuda里线程号的选取方式,这个其实是和
func(a_gpu, b_gpu, grid=(int(acc_data.shape[0]/250),), block=(250, 1, 1))
密切相关的,前提是了解GPU线程,线程块概念
在这里插入图片描述
线程号的计算方式(不一定都对,至少情况4是没问题的):

# 1.使用N个线程块,每一个线程块只有一个线程
dim3 dimGrid(N);
dim3 dimBlock(1);
threadId = blockIdx.x;

# 2.使用M×N个线程块,每个线程块1个线程
dim3 dimGrid(M,N);
dim3 dimBlock(1);
blockIdx.x #取值0到M-1
blcokIdx.y #取值0到N-1
pos = blockIdx.y * gridDim.x + blockIdx.x; #其中gridDim.x等于M

# 3.使用一个线程块,该线程具有N个线程
dim3 dimGrid(1);
dim3 dimBlock(N);
threadId = threadIdx.x;

# 4.使用M个线程块,每个线程块内含有N个线程
dim3 dimGrid(M);
dim3 dimBlock(N);
threadId = threadIdx.x + blcokIdx.x*blockDim.x;

# 5.使用M×N的二维线程块,每一个线程块具有P×Q个线程
dim3 dimGrid(M, N);
dim3 dimBlock(P, Q);
threadId.x = blockIdx.x*blockDim.x+threadIdx.x;
threadId.y = blockIdx.y*blockDim.y+threadIdx.y;

step03

最后就是多理解多敲吧,找到合适可以修改的地方进行修改,GPU并行这块就靠pycuda了,另外在CPU的并行计算上有三个适用于pandas的库

# 1.用parallel_apply代替apply,仅限linux和Mac系统
from pandarallel import pandarallel
pandarallel.initialize()

# 2.针对apply
import swifter
data.swifter.apply(lambda)

# 3.直接替代pandas,适代码而用
import modin.pandas as pd

另外就是用多线程多进程来处理了

import threadpool
thread_data=list(np.array(km_stake))[1:]
# print(thread_data)
pool = threadpool.ThreadPool(8)
requests = threadpool.makeRequests(apply_work, thread_data)
[pool.putRequest(req) for req in requests]
pool.wait()
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
PyCUDA是一个用于Python的GPU计算库,它允许使用NVIDIA CUDA平台在Python中编写CUDA代码。下面是一个简单的PyCUDA教程,它将向您展示如何安装和使用该库。 1. 安装CUDA 在开始使用PyCUDA之前,您需要安装CUDA。请确保您的计算机上安装了适当版本的CUDA。可以从NVIDIA的官方网站上下载并安装。 2. 安装PyCUDA 在安装CUDA之后,您需要安装PyCUDA。可以使用pip来安装PyCUDA。打开终端并运行以下命令: ``` pip install pycuda ``` 注意:在安装PyCUDA之前,您需要确保已安装以下依赖项: - NVIDIA CUDA Toolkit - Python NumPy - Python setuptools 3. 编写第一个PyCUDA程序 现在,您已经安装了PyCUDA,让我们编写一个简单的程序来测试一下。 ```python import pycuda.driver as cuda import pycuda.autoinit from pycuda.compiler import SourceModule # 定义CUDA内核 mod = SourceModule(""" __global__ void multiply_them(float *dest, float *a, float *b) { const int i = threadIdx.x; dest[i] = a[i] * b[i]; } """) # 获取内核函数 multiply_them = mod.get_function("multiply_them") # 定义输入 a = cuda.InOut(np.ones(10).astype(np.float32)) b = cuda.InOut(np.ones(10).astype(np.float32)) dest = cuda.InOut(np.zeros(10).astype(np.float32)) # 调用内核函数 multiply_them(dest, a, b, block=(10, 1, 1)) # 打印输出 print(dest) ``` 代码中的注释解释了每个步骤的作用。 这是一个非常基本的例子,但它演示了如何使用PyCUDACUDA设备上运行一个简单的内核函数。 4. 总结 这就是一个简单的PyCUDA教程。通过这个教程,您应该已经了解了PyCUDA的基本知识,并学会了如何安装和使用它。如果您想深入学习PyCUDA,可以查看PyCUDA文档以获取更多信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值