在使用GPU之前,要对GPU进行一些配置,简单记录一下流程。
class gpu
{
public:
//并行计算内部句柄
cl_device_id* devices;//设备
cl_context _context;//上下文
cl_command_queue _commandQueue;//命令队列
int dev_id=0;
int argNum = 0;
gpu();
//初始化OpenCL
cl_int CL_Init(int plat_id);
//内存申请(数据指针,大小)
cl_mem gmalloc(void* data, unsigned long size, cl_mem_flags flags);
//运行
void run(int dim, gpu_program program, size_t size_xy[2], size_t localWorkSize[2]);
~gpu();
};
我的目的不单单是写OpenCL程序,我想写一个机器学习的框架(应该是加速工具吧),所以,这里开始就比较模块化了。
其中cl_device_id * devices 是设备指针,理解为指向一个设备,到后面可以了解到具体是神设备,cl_context _context,是设备上下文,应该就是设备的驱动之类的信息。cl_command_queue _commandQueue是命令队列,我们这里使用了通用计算的功能,这个命令队列也就是只接受计算相关指令了,有什么指令直接上传到队列,等待GPU相应。
下面是初始化GPU的步骤,总结一下主要分几个主要步骤
1.先获取指定平台,这个平台就是你电脑里安装的设备,例如是英伟达,AMD,还是核显。
2.在指定平台上获取对应的设备,比如你安装了一个英伟达的显卡,那么这一步你将获取到一个英伟达显卡设备,如果你安装了3块英伟达显卡,这一步你应该能获得三个对应的设备。
3.然后和驱动程序建立好交互。
4.创建 与显卡沟通的通道。
以上四个步骤是我自己理解总结的,可能有不准确的地方。
cl_int gpu::CL_Init(int plat_id)
{
cl_uint platformNum = 0;
//获取平台数目,intel,amd,nvidia....
cl_int status = clGetPlatformIDs(0, NULL, &platformNum);
if (status != CL_SUCCESS)
return 1;
//获取指定平台ID
cl_platform_id platform = NULL;
if (platformNum > 0)
{
cl_platform_id* p_id = new cl_platform_id[platformNum];
memset(p_id, 0, platformNum * sizeof(cl_platform_id));
//获得平台ID
clGetPlatformIDs(platformNum, p_id, NULL);
platform = p_id[plat_id];
//delete[] p_id;
}
if (platform == NULL)
return 2;
//获取对应平台GPU数目
cl_uint deviceNum = 0;
cl_device_id * device = NULL;
clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 0, NULL, &deviceNum);
if (deviceNum == 0)
{
clGetDeviceIDs(platform, CL_DEVICE_TYPE_CPU, 0, NULL, &deviceNum);
// 为设备分配空间
device = new cl_device_id[deviceNum];// (cl_device_id*)malloc(deviceNum * sizeof(cl_device_id));
// 获得设备
clGetDeviceIDs(platform, CL_DEVICE_TYPE_CPU, deviceNum, device, NULL);
}
else
{
device = new cl_device_id[deviceNum];
clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, deviceNum, device, NULL);
}
//创建设备上下文
cl_context context = clCreateContext(NULL, 1, device, NULL, NULL, NULL);
if (NULL == context)
return 3;
//创建命令队列
cl_command_queue commandQueue = clCreateCommandQueue(context, device[0], 0, NULL);
if (NULL == commandQueue)
return 4;
//返回重要信息
devices = device;
_context = context;
_commandQueue = commandQueue;
return 0;
}
有了以上步骤,获得了前面介绍的那三个参数,就可以进行GPU计算 了。