OpenCL 设备

每个平台可能关联不同的设备,在把内核程序送到OpenCL设备上执行前,编程人员需要指定执行该内核代码的计算设备。

clGetDeviceIDs

OpenCL中设备对象的类型为cl_device_id,我们可以通过以下函数来查询支持OpenCL设备列表:

cl_int clGetDeviceIDs(cl_platform_id   platform ,
                          cl_device_type   device_type ,
                          cl_uint           num_entries ,
                          cl_device_id    *devices ,
                          cl_uint          *num_devices )

该函数与clGetPlatformIDs函数类似,第一次调用时,devices参数设置为NULL,num_devices返回指定平台中的设备数;

第二次调用时,根据第一次调用得到设备数量分配设备空间,调用该函数来初始化可用设备。

需要注意的是,如果devices不为NULL,num_entries的值必须大于0,num_entries用于指定devices所指向的设备对象列表中最多可存放多少个设备对象,这样此函数所输出的设备对象个数不会超过num_entries的值。而num_devices则输出实际给出的设备对象的个数。

通过下面的代码清单来说明以上操作:

cl_uint num_platform;
cl_uint num_device;
cl_platform_id *platform;
cl_device_id *devices;
cl_int err;
err = clGetPlatformIDs(0, 0, &num_platform);
platform = (cl_platform_id *)malloc(sizeof(cl_platform_id) *
                                          num_platform);
err = clGetPlatformIDs(num_platform, platform, NULL);
//获得第一个平台上的设备数量
err = clGetDeviceIDs(platform[0], CL_DEVICE_TYPE_GPU, 0, NULL,
                        &num_device);
devices = (cl_device_id *)malloc(sizeof(cl_device_id) *
                                        num_device);
//初始化可用的设备
err = clGetDeviceIDs(platform[0], CL_DEVICE_TYPE_GPU, num_device,
                        devices, NULL);

在上面的例子中,我们查询第一个平台上GPU类型的可用OpenCL设备数量,并初始化这些设备。

对于上述例子,查询的是GPU类型的OpenCL设备。对于函数中的device_type参数,可用类型如下表所示:

OpenCL设备类型

clGetDeviceInfo

给定一个OpenCL设备后,使用如下函数可以获得设备的各个属性信息:

cl_int clGetDeviceInfo(cl_device_id    device ,
                            cl_device_info param_name ,
                            size_t           param_value_size ,
                            void            *param_value ,
                            size_t          *param_value_size_ret )

这个函数返回给定设备的属性信息。

第一个参数device指定查询的设备。

第二个参数param_name为查询平台的属性信息,param_name的取值如下表所示。

最后一个参数param_value_size_ret返回属性信息实际的长度。

第四个参数param_value为指向保存平台属性信息的指针。

第三个参数param_value_size指定param_value参数指向的内存空间大小,这个值必须大于第四个参数的返回值。

OpenCL设备查询

OpenCL设备查询

OpenCL设备查询

OpenCL设备查询

下面代码清单展示了如何使用clGetDeviceInfo()来查询指定平台上GPU设备的属性信息。

#include 〈stdio.h>
#include 〈stdlib.h>
#ifdef _APPLE_
#include 〈OpenCL/cl.h>
#else
#include 〈CL/cl.h>
#endif
void checkErr(cl_int err, int num)
{
    if(CL_SUCCESS != err)
    {
        printf("OpenCL error(%d) at %d\n", err, num - 1);
    }
}
int main(int argc, char **argv)
{
    cl_device_id *device;
    cl_platform_id platform;
    cl_int err;
    cl_uint NumDevice;
    //选择第一个平台
    err = clGetPlatformIDs(1, &platform, NULL);
    checkErr(err, _LINE_);
    err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU,
                              0, NULL, &NumDevice);
    checkErr(err, _LINE_);
    device = (cl_device_id *)malloc(sizeof(cl_device_id) *
                                          NumDevice);
    //选择GPU设备
    err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU,
                              NumDevice, device, NULL);
    checkErr(err, _LINE_);
    for(int i = 0; i 〈 NumDevice; i++)
    {
        //查询设备名称
        char buffer[100];
        err = clGetDeviceInfo(device[i], CL_DEVICE_NAME,
                                    100, buffer, NULL);
        checkErr(err, _LINE_);
        printf("Device Name:%s\n", buffer);
        //查询设备计算单元最大数目
        cl_uint UnitNum;
        err = clGetDeviceInfo(device[i],
                                    CL_DEVICE_MAX_COMPUTE_UNITS,
                                    sizeof(cl_uint), &UnitNum, NULL);
        checkErr(err, _LINE_);
        printf("Compute Units Number: %d\n", UnitNum);
        //查询设备核心频率
        cl_uint frequency;
        err = clGetDeviceInfo(device[i],
                          CL_DEVICE_MAX_CLOCK_FREQUENCY,
                          sizeof(cl_uint), &frequency, NULL);
        checkErr(err, _LINE_);
        printf("Device Frequency: %d(MHz)\n", frequency);
        //查询设备全局内存大小
        cl_ulong GlobalSize;
        err = clGetDeviceInfo(device[i], CL_DEVICE_GLOBAL_MEM_SIZE,
                          sizeof(cl_ulong), &GlobalSize, NULL);
        checkErr(err, _LINE_);
        printf("Device Global Size: %0.0f(MB)\n",
        (float)GlobalSize / 1024 / 1024);
        //查询设备全局内存缓存行
        cl_uint GlobalCacheLine;
        err = clGetDeviceInfo(device[i],
                          CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE,
                          sizeof(cl_uint), &GlobalCacheLine,
                          NULL);
        checkErr(err, _LINE_);
        printf("Device Global CacheLine: %d(Byte)\n",
        GlobalCacheLine);
        //查询设备支持的OpenCL版本
        char DeviceVersion[100];
        err = clGetDeviceInfo(device[i], CL_DEVICE_VERSION,
                          100, DeviceVersion, NULL);
        checkErr(err, _LINE_);
        printf("Device Version:%s\n", DeviceVersion);
        //查询设备拓展名
        char *DeviceExtensions;
        cl_uint ExtenNum;
        err = clGetDeviceInfo(device[i], CL_DEVICE_EXTENSIONS,
                          0, NULL, &ExtenNum);
        checkErr(err, _LINE_);
        DeviceExtensions = (char *)malloc(ExtenNum);
        err = clGetDeviceInfo(device[i], CL_DEVICE_EXTENSIONS,
                          ExtenNum, DeviceExtensions, NULL);
        checkErr(err, _LINE_);
        printf("Device Extensions:%s\n", DeviceExtensions);
        free(DeviceExtensions);
  }
  free(device);
  return 0;
}

在AMD Radeon R9 285设备上,上述代码输出结果如下:

Device Name:Tonga
   Compute Units Number: 28
   Device Frequency: 965(MHz)
   Device Global Size: 2048(MB)
   Device Global CacheLine: 64(Byte)
   Device Version:OpenCL 1.2 AMD-APP (1642.5)
   Device Extensions:cl_khr_fp64 cl_amd_fp64 cl_khr_global_int32_base_atomics cl_
khr_global_int32_extended_atomics cl_khr_local_int32_base_atomics cl_khr_local_
int32_extended_atomics cl_khr_int64_base_atomics cl_khr_int64_extended_atomics cl_
khr_3d_image_writes cl_khr_byte_addressable_store cl_khr_gl_sharing cl_ext_atomic_
counters_32 cl_amd_device_attribute_query cl_amd_vec3 cl_amd_printf cl_amd_media_
ops cl_amd_media_ops2 cl_amd_popcnt cl_khr_d3d10_sharing cl_khr_d3d11_sharing cl_
khr_dx9_media_sharing cl_khr_image2d_from_buffer cl_khr_spir cl_khr_gl_event

需要注意的是:查询设备不同的属性信息对应的返回值类型不同。初学者可能对此不太注意,接收返回值的变量与所需类型不一致,造成查询属性信息输出结果不正确。

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程