Python是目前较流行的一种科学计算语言。语法简洁,上手快,易于维护的优点。但其运算速度是真心的慢。那我们能否利用Python的简洁+OpenCL的运算能力呢?答案是可以的,那就是PyOpenCL。
目录
预备知识
OpenCL 是一个为异构平台编写程序的框架,此异构平台可由CPU,GPU或其他类型的处理器组成。我们先来复习下CPU和GPU的相关知识:CPU的设计让其比较擅长于处理不规则数据结构和不可预测的存取模式,以及递归算法、分支密集型代码和单线程程序。这类程序任务拥有复杂的指令调度、循环、分支、逻辑判断以及执行等步骤。而GPU擅于处理规则数据结构和可预测存取模式。
PyOpenCL安装
#这里只介绍Linux环境下安装方法
sudo apt-get install python3-pyopencl
基本概念
- 计算平台指机器设备对OpenCL某个版本的具体实现。
- 一台计算机上可以有多个计算平台,一个计算平台上可以有多个计算核心。
- 多核CPU和多CPU是两回事,除非你的主板上插有两块CPU,这种情况也只有服务器主板上才会出现多CPU情况。
- 一个计算平台设备里面,可以有多个计算核心,每个核心就是实质的计算部件。像4核CPU就是一个计算平台设备里面有4个计算部件。可以并行执行四个运算操作。
因此我们除了要获取系统里计算平台设备信息外,还要获取每个设备里面的计算核心信息,这样才可以对我们的程序进行最大优化。
设备遍历源码
import pyopencl as cl
#显示OPENCL版本号,cl.h的版本号
print("CL_VERSION:",cl.VERSION)
print("CL_HEADER_VERSION:",cl.get_cl_header_version())
print()
#获取当前所有计算平台
platforms = cl.get_platforms()
print("Platform num:",len(platforms))
#遍历所有平台中的所有计算设备,并显示它们的信息
for plat in platforms:
print("--Platform Name:",plat.get_info(cl.platform_info.NAME))
#print("--Platform Extensions:",plat.get_info(cl.platform_info.EXTENSIONS))
print("--Platform Profile:",plat.get_info(cl.platform_info.PROFILE))
print("--Platform Vendor:",plat.get_info(cl.platform_info.VENDOR))
print("--Platform Version:",plat.get_info(cl.platform_info.VERSION))
devices = plat.get_devices(cl.device_type.ALL)
print("--device num:",len(devices))
for device in devices:
print("----Name:",device.get_info(cl.device_info.NAME))
print("----OpenCL_C_Version:",device.get_info(cl.device_info.OPENCL_C_VERSION))
print("----Vendor:",device.get_info(cl.device_info.VENDOR))
print("----Version:",device.get_info(cl.device_info.VERSION))
print("----Driver Version:",device.get_info(cl.device_info.DRIVER_VERSION))
print("----MAX_WORK_GROUP_SIZE:",device.get_info(cl.device_info.MAX_WORK_GROUP_SIZE))
print("----MAX_COMPUTE_UNITS:",device.get_info(cl.device_info.MAX_COMPUTE_UNITS))
print("----MAX_WORK_ITEM_SIZES:",device.get_info(cl.device_info.MAX_WORK_ITEM_SIZES))
print("----LOCAL_MEM_SIZE:",device.get_info(cl.device_info.LOCAL_MEM_SIZE))
运行结果
C++版遍历程序
C++的SDK工具下载地址:
Intel OpenCL SDK:https://software.intel.com/en-us/intel-opencl/download
AMD OpenCL SDK:https://github.com/GPUOpen-LibrariesAndSDKs/OCL-SDK/releases
#include <iostream>
#include <malloc.h>
#include <CL/cl.h>//包含CL的头文件
using namespace std;
//根据参数,判断设备类别。是CPU、GPU、ACCELERATOR或其他设备
const char* GetDeviceType(cl_device_type it)
{
if(it == CL_DEVICE_TYPE_CPU)
return "CPU";
else if(it== CL_DEVICE_TYPE_GPU)
return "GPU";
else if(it==CL_DEVICE_TYPE_ACCELERATOR)
return "ACCELERATOR";
else
return "DEFAULT";
}
int main()
{
char dname[512];
cl_device_id devices[20];
cl_platform_id* platform_id = NULL;
cl_uint num_devices;
cl_device_type int_type;
cl_ulong long_entries;
cl_uint num_platform;
cl_int err;
//查询系统上可用的计算平台,可以理解为初始化
err = clGetPlatformIDs(0,NULL,&num_platform);
if(err!=CL_SUCCESS)
{
cout<<"clGetPlatformIDs error"<<endl;
return 0;
}
cout<<"PlatForm num:"<<num_platform<<endl;
int st=0;
platform_id = new cl_platform_id[num_platform];
err = clGetPlatformIDs(num_platform,platform_id,NULL);
if(err!=CL_SUCCESS)
{
cout<<"clGetPlatformIDs error"<<endl;
return 0;
}
for(st=0;st<num_platform;st++)
{
cout<<"----------------------------------"<<endl;
cout<<"Platform "<<st+1<<endl;
//获取可用计算平台的名称
clGetPlatformInfo(platform_id[st],CL_PLATFORM_NAME,512,dname,NULL);
cout<<"CL_PLATFORM_NAME:"<<dname<<endl;
//获取可用计算平台的版本号,即OpenCL的版本号
clGetPlatformInfo(platform_id[st],CL_PLATFORM_VENDOR,512,dname,NULL);
cout<<"CL_PLATFORM_VERSION:"<<dname<<endl;
//获取可用计算平台的设备数目
clGetDeviceIDs(platform_id[st],CL_DEVICE_TYPE_ALL,20,devices,&num_devices);
cout<<"Device num:"<<num_devices<<endl;
unsigned int n=0;
//循环两次,检测两个设备的属性
for(n=0;n<num_devices;n++)
{
cout<<endl<<"Device "<<n+1<<endl;
//获取设备名称
clGetDeviceInfo(devices[n],CL_DEVICE_NAME,512,dname,NULL);
cout<<"Device :"<<dname<<endl;
//获取设备类别
clGetDeviceInfo(devices[n],CL_DEVICE_TYPE,sizeof(cl_device_type),
&int_type,NULL);
cout<<"Device Type:"<<GetDeviceType(int_type)<<endl;
//获取设备版本号
clGetDeviceInfo(devices[n],CL_DRIVER_VERSION,512,dname,NULL);
cout<<"Device version:"<<dname<<endl;
//获取设备全局内存大小
clGetDeviceInfo(devices[n],CL_DEVICE_GLOBAL_MEM_SIZE,
sizeof(cl_ulong),&long_entries,NULL);
cout<<"Device global mem(MB):"<<
long_entries/1024/1024<<endl;
//获取设备CACHE内存大小
clGetDeviceInfo(devices[n],CL_DEVICE_GLOBAL_MEM_CACHE_SIZE,
sizeof(cl_ulong),&long_entries,NULL);
cout<<"Device global mem cache(KB):"<<
long_entries/1024<<endl;
//获取本地内存大小
clGetDeviceInfo(devices[n],CL_DEVICE_LOCAL_MEM_SIZE,
sizeof(cl_ulong),&long_entries,NULL);
cout<<"Device Locale mem(KB) :"<<long_entries/1024<<endl;
//获取设备频率
clGetDeviceInfo(devices[n],CL_DEVICE_MAX_CLOCK_FREQUENCY,
sizeof(cl_ulong),&long_entries,NULL);
cout<<"Device Max clock(MHz) :"<<long_entries<<endl;
//获取最大工作组数
clGetDeviceInfo(devices[n],CL_DEVICE_MAX_WORK_GROUP_SIZE,
sizeof(cl_ulong),&long_entries,NULL);
cout<<"Device Max Group size :"<<long_entries<<endl;
//获取最大计算核心数
clGetDeviceInfo(devices[n],CL_DEVICE_MAX_COMPUTE_UNITS,
sizeof(cl_ulong),&long_entries,NULL);
cout<<"Device Max parallel cores:"<<long_entries<<endl;
}
}
return 0;
}