OpenCL API

1 OpenCL平台

1.1 查询OpenCL平台数量

cl_int clGetPlatformIDs(cl_uint num_entries, cl_platform_id* platforms, cl_uint* num_platforms);
// cl_uint num_entries:可以获得的平台ID的数量限制。如果platforms不是NULL,num_entries就一定要大于0。
// cl_platform_id* platforms:平台ID的集合
// cl_uint* num_platforms:获取到的平台的数量
// 可以将num_entries和platforms分别设置为0和NULL来查询可用的平台数量。

该接口返回值:

  • 正确执行会返回CL_SUCCESS
  • num_entries为0,platforms不为NULL,返回 CL_INVALID_VALUE
  • platforms和num_platforms都为NULL,返回CL_INVALID_VALUE
  • 在宿主机申请内存失败,返回 CL_OUT_OF_HOST_MEMORY

举例:

cl_int errNum;
cl_uint numPlatforms;
cl_platform_id *platformIds;
errNum = clGetPlatformIDs(0, NULL, &numPlatforms);
platformIds = (cl_platform_id *)alloca(sizeof(cl_platform_id) * numPlatforms);
errNum = clGetPlatformIDs(numPlatforms, platformIds, NULL);

1.2 查询OpenCL平台信息

cl_int clGetPlatformInfo(cl_platform_id platform, cl_platform_info param_name,
  						 size_t param_value_size, void* param_value, size_t* param_value_size_ret);
// cl_platform_id platform:待查询的platformID
// cl_platform_info param_name:想要查询的平台信息,如CL_PLATFORM_PROFILE、CL_PLATFORM_VERSION、CL_PLATFORM_NAME等。更多的请查询OpenCL API spec。
// size_t param_value_size:查询的平台信息结果的内存大小
// void* param_value:查询的平台信息结果
// size_t* param_value_size_ret:真实的平台信息结果的大小
// 可以将param_value_size和param_value分别设置为0和NULL,来查询平台信息结果的大小

参数cl_platform_info param_name可选值如下:
在这里插入图片描述
在这里插入图片描述

该接口返回值:

  • 正确执行会返回CL_SUCCESS
  • platform不是一个合法的platform ID,返回CL_INVALID_PLATFORM。
  • param_name是非法的,返回CL_INVALID_VALUE。
  • param_value_size小于真实的平台信息结果的大小,返回CL_INVALID_VALUE。
  • 在宿主机申请内存失败,返回 CL_OUT_OF_HOST_MEMORY

举例:

cl_int err;
size_t size;

err = clGetPlatformInfo(platformID, CL_PLATFORM_NAME, 0, NULL, &size);
char *platformName = (char *)alloca(sizeof(char) * size);
err = clGetPlatformInfo(platformID, CL_PLATFORM_NAME, size, platformName, 0);

err = clGetPlatformInfo(platformID, CL_PLATFORM_VENDOR, 0, NULL, &size);
char *vendorName = (char *)alloca(sizeof(char) * size);
err = clGetPlatformInfo(platformID, CL_PLATFORM_NAME, size, vendorName, 0);

std::cout << "Platform name:" << platformName << std::endl
		  << "Vendor name:" << vendorName << std::endl;

2 OpenCL 设备

2.1 查询OpenCL设备ID

cl_int clGetDeviceIDs(cl_platform_id platform, cl_device_type device_type, cl_uint num_entries,
 					  cl_device_id* devices, cl_uint* num_devices);
// cl_platform_id platform:待查询设备所属的平台ID
// cl_device_type device_type:查询的设备类型,如CL_DEVICE_TYPE_CPU 、CL_DEVICE_TYPE_GPU 等,更多的请查询OpenCL API spec。
// cl_uint num_entries:查询的设备数量限制。0 < num_entries < 设备数量
// cl_device_id* devices:查询到的设备ID
// cl_uint* num_devices:查询到的设备数量
// 可以将num_entries和devices设为0和NULL,来查询平台的设备数量

参数cl_device_type device_type可选值为:
在这里插入图片描述

该接口返回值:

  • 正确执行会返回CL_SUCCESS
  • platform不是一个合法的platform ID,返回CL_INVALID_PLATFORM。
  • device_type不是一个合法的值,返回CL_INVALID_DEVICE_TYPE
  • num_entries为0,devices 不为NULL,返回 CL_INVALID_VALUE
  • num_devices和devices 都为NULL,返回CL_INVALID_VALUE
  • 没有找到匹配的device_type,返回CL_DEVICE_NOT_FOUND
  • 在设备上申请内存失败,返回CL_OUT_OF_RESOURCES。
  • 在宿主机申请内存失败,返回 CL_OUT_OF_HOST_MEMORY

举例:

cl_int errNum;
cl_int numDevices;
cl_device_id deviceIDs[1];
errNum = clGetDeviceIDs(platformId, CL_DEVICE_TYPE_GPU, 0, NULL, numDevices);
if(numDevices < 1) {
	std::cout << "No device found for platform:" << platform << std::endl;
	exit(1);
}

errNum = clGetDeviceIDs(platformId, CL_DEVICE_TYPE_GPU, 1, &deviceIDs[0], NULL);

2.2 查询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);
// cl_device_id device:待查询的设别ID
// cl_device_info param_name:想要查询的设备信息名。如CL_DEVICE_MAX_COMPUTE_UNITS等。更多的查询spec
// size_t param_value_size:查询到的设备信息结果内存大小
// void* param_value:查询到的设备信息结果
// size_t* param_value_size_ret:真实的设备信息结果内存大小
// 可以将param_value_size和param_value分别设置为0和NULL,获取真实的设备信息结果内存大小

参数cl_device_info param_name可选值太多,请自行查阅OpenCL spec。下面只截图一部分:
CL_DEVICE_TYPE:device类型。
CL_DEVICE_VENDOR_ID :device产商
CL_DEVICE_MAX_COMPUTE_UNITS:CU的最大数量
CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS:work_item的最大维度,一般是3
CL_DEVICE_MAX_WORK_ITEM_SIZES:每个dimension能够指定的最大work_item数量,返回size_t[]类型
CL_DEVICE_MAX_WORK_GROUP_SIZE:一个work_group中的work_item的最大数量
CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR
CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT
CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT
CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG
CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT
CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE
CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF:一个向量中标量的个数
CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR
CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT
CL_DEVICE_NATIVE_VECTOR_WIDTH_INT
CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG
CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT
CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE
CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF:同上
CL_DEVICE_MAX_CLOCK_FREQUENCY:device的时钟频率
CL_DEVICE_ADDRESS_BITS :全局内存地址空间大小,一般是32或64
CL_DEVICE_MAX_MEM_ALLOC_SIZE:内存对象能够分配的最大空间,一般是MAX(MIN(1024 × 1024 ×
1024, 1/4th of CL_DEVICE_GLOBAL_MEM_SIZE), 32 ×1024 × 1024)
CL_DEVICE_IMAGE_SUPPORT :device是否支持image内存
CL_DEVICE_MAX_READ_IMAGE_ARGS:只读的image对象的最大数量,最小是128
CL_DEVICE_MAX_WRITE_IMAGE_ARGS:只写的image对象的最大数量,最小是64
CL_DEVICE_MAX_READ_WRITE_IMAGE_ARGS:
CL_DEVICE_IL_VERSION:中间语言版本,主要通过中间语言创建程序对象
CL_DEVICE_ILS_WITH_VERSION:device支持的中间语言的描述
太多了,心态崩了。。。。。。。。。。。。
在这里插入图片描述

该接口返回值:

  • 正确执行会返回CL_SUCCESS
  • device是非法的,返回CL_INVALID_DEVICE.
  • param_name的值非法,返回CL_INVALID_VALUE
  • param_value_size小于真实的设备信息结果内存大小,同时param_value不是NULL,返回CL_INVALID_VALUE
  • param_name是不支持的扩展,返回CL_INVALID_VALUE
  • 在设备上申请内存失败,返回CL_OUT_OF_RESOURCES。
  • 在宿主机申请内存失败,返回 CL_OUT_OF_HOST_MEMORY

举例:

cl_int err;
size_t size;
cl_int maxComputeUnits;
err = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(cl_uint), &maxComputeUnits, &size);
std::cout << "device has max compute units:" << maxComputeUnits << std::endl;

3 OpenCL 上下文

3.1 创建上下文

cl_context clCreateContext(
  const cl_context_properties* properties,
  cl_uint num_devices,
  const cl_device_id* devices,
  void (CL_CALLBACK* pfn_notify)(const char* errinfo, const void* private_info, size_t cb, void* user_data),
  void* user_data,
  cl_int* errcode_ret);
 // const cl_context_properties* properties:上下文属性,如CL_CONTEXT_PLATFORM指定使用的平台和CL_CONTEXT_INTEROP_USER_SYNC
 // cl_uint num_devices: 上下文中有几个device
 // const cl_device_id* devices:deivce ID的集合
 // void (CL_CALLBACK* pfn_notify)(const char* errinfo, const void* private_info, size_t cb, void* user_data):应用程序注册的回调函数,用来报告上下文执行中的错误信息。
 	// errinfo:指向一个错误信息字符串
 	// private_info和cb表示OpenCL实现返回的二进制数据的指针,可用于记录有助于调试错误的附加信息
 	// user_data:指向用户提供的数据
 // void* user_data:回调函数pfn_notify的参数	
 // cl_int* errcode_ret:错误返回值。没有错误,则返回NULL
 // 

该接口返回值:

  • 正确执行会返回一个合法的非0上下文,并且errcode_ret值为CL_SUCCESS
  • properties为NULL或者properties指向的platform非法,则返回CL_INVALID_PLATFORM。
  • properties不是一个合法的属性,则返回CL_INVALID_PROPERTY。
  • devices为NULL,返回CL_INVALID_VALUE。
  • num_devices为0,返回CL_INVALID_VALUE
  • pfn_notify为NULL,但user_data不是NULL,返回CL_INVALID_VALUE
  • devices中有一个非法device,返回CL_INVALID_DEVICE。
  • devices中有一个device不可获得,返回CL_DEVICE_NOT_AVAILABLE。
  • 在设备上申请内存失败,返回CL_OUT_OF_RESOURCES。
  • 在宿主机申请内存失败,返回 CL_OUT_OF_HOST_MEMORY

举例:

void CL_CALLBACK contextCallback(
	const char * errInfo,
	const void * private_info,
	size_t cb,
	void * user_data)
{
	std::cout << "Error occured during context use: " << errInfo << std::endl;
	// should really perform any clearup and so on at this point
	// but for simplicitly just exit.
	exit(1);
}
    cl_context_properties contextProperties[] =
    {
        CL_CONTEXT_PLATFORM,
        (cl_context_properties)platformIDs[i],
        0
    };
    context = clCreateContext(
		contextProperties, 
		numDevices,
        deviceIDs, 
		&contextCallback,
		NULL, 
		&errNum);

通过指定的设备类型创建上下文:

cl_context clCreateContextFromType(
  const cl_context_properties* properties,
  cl_device_type device_type,
  void (CL_CALLBACK* pfn_notify)(const char* errinfo, const void* private_info, size_t cb, void* user_data),
  void* user_data,
  cl_int* errcode_ret);

3.2 获取上下文信息

cl_int clGetContextInfo(
  cl_context context,
  cl_context_info param_name,
  size_t param_value_size,
  void* param_value,
  size_t* param_value_size_ret);
// cl_context context:待查询的上下文
// cl_context_info param_name
// size_t param_value_size
// void* param_value
// size_t* param_value_size_ret

举例:

void CL_CALLBACK contextCallback(
	const char * errInfo,
	const void * private_info,
	size_t cb,
	void * user_data)
{
	std::cout << "Error occured during context use: " << errInfo << std::endl;
	// should really perform any clearup and so on at this point
	// but for simplicitly just exit.
	exit(1);
}
    cl_context_properties contextProperties[] =
    {
        CL_CONTEXT_PLATFORM,
        (cl_context_properties)platformIDs[i],
        0
    };
    context = clCreateContext(
		contextProperties, 
		numDevices,
        deviceIDs, 
		&contextCallback,
		NULL, 
		&errNum);
	errNum = clGetContextInfo(context, CL_CONTEXT_DEVICES, 0, NULL, &size);
	cl_device_id *deviceID = (cl_device_id *)alloca(sizeof(cl_device_id) * size);
	errNum = clGetContextInfo(context, CL_CONTEXT_DEVICES, size, deviceID, NULL);
	for(size_t i = 0; i < size / sizeof(cl_device_id); i++) {
		cl_device_type type;
		clGetDeviceInfo(device[i], CL_DEVICE_TYPE, sizeof(cl_device_type), &type, NULL);
		switch(type) {
			case CL_DEVICE_TYPE_CPU:
			case CL_DEVICE_TYPE_GPU:
		}

增加上下文引用计数

cl_int clRetainContext(
  cl_context context);

减少上下文引用计数

cl_int clReleaseContext(
  cl_context context);

4 命令队列

4.1 创建命令队列

cl_command_queue clCreateCommandQueue(
  cl_context context,
  cl_device_id device,
  cl_command_queue_properties properties,
  cl_int* errcode_ret);
  // cl_context context:一个合法的上下文
  // cl_device_id device:与context关联的一个合法的设备ID
  // cl_command_queue_properties properties:命令队列的属性,有CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE和CL_QUEUE_PROFILING_ENABLE两个值可选
  // cl_int* errcode_ret:错误码返回值

cl_command_queue_properties properties的可选值如下:
在这里插入图片描述

5 程序

5.1 创建程序

cl_program clCreateProgramWithSource(
  cl_context context,
  cl_uint count,
  const char** strings,
  const size_t* lengths,
  cl_int* errcode_ret);
  // cl_context context:一个合法的OpenCL上下文
  // cl_uint count:参数const char** strings中字符串指针数量
  // const char** strings:kernel函数源代码字符串,包含count个字符串指针的。所有字符串结合在一起就是kernel源码
  // const size_t* lengths:参数const char** strings中各个字符串的长度。表示字符串是否以空字符结尾。如果lengths中某个元素为0,则对应的字符串以空字符结尾;如果lengths为NULL,则所有字符串都是以空字符结尾。
  // cl_int* errcode_ret:错误码返回值。

5.2 编译程序

cl_int clBuildProgram(
  cl_program program,
  cl_uint num_devices,
  const cl_device_id* device_list,
  const char* options,
  void (CL_CALLBACK* pfn_notify)(cl_program program, void* user_data),
  void* user_data);
  // cl_program program:待编译的程序对象
  // cl_uint num_devices:device_list中的device的数量
  // const cl_device_id* device_list:与program关联的device列表,如果为NULL,则为上下文中所有device都编译执行program。如果不为NULL,则在指定的device上编译执行program
  // const char* options:一个空字符结尾的字符串,内容是编译程序的编译选项。具体有哪些编译选项,见3.0 spec 213页 5.8.6. Compiler Options
  // void (CL_CALLBACK* pfn_notify)(cl_program program, void* user_data):用户注册的回调函数,在编译program时调用。如果pfn_notify为NULL,则在完成构建之前,clBuildProgram不会返回。如果pfn_notify不为NULL,则可以在完成构建之前返回,并在构建过程中调用pfn_notify。pfn_notify的作用之一是让构建排队(因为可能有多个device需要构建),使之异步完成,同时应用程序也能继续执行其他工作。
  // void* user_data:

获取编译失败信息

cl_int clGetProgramBuildInfo(
  cl_program program,
  cl_device_id device, // device_list中的设备之一
  cl_program_build_info param_name, //CL_PROGRAM_BUILD_LOG
  size_t param_value_size,
  void* param_value,
  size_t* param_value_size_ret);

6 内核

6.1 创建内核对象

cl_kernel clCreateKernel(
  cl_program program,
  const char* kernel_name, // kernel_name要与kernel实现的函数名相同
  cl_int* errcode_ret);

7 buffer

7.1 创建buffer

cl_mem clCreateBuffer(
  cl_context context,
  cl_mem_flags flags,
  size_t size,
  void* host_ptr,
  cl_int* errcode_ret);
  // cl_context context:
  // cl_mem_flags flags:内存的标志。如CL_MEM_READ_WRITE、CL_MEM_WRITE_ONLY、CL_MEM_READ_ONLY、CL_MEM_USE_HOST_PTR等
  // size_t size:
  // void* host_ptr:
  // cl_int* errcode_ret:

7.2 设置参数

cl_int clSetKernelArg(
  cl_kernel kernel,
  cl_uint arg_index, // 参数的索引,0表示kernel函数的第一个参数,1表示第二个
  size_t arg_size, //参数的大小,一般时sizeof(param_type)
  const void* arg_value); //参数地址

8 排队

cl_int clEnqueueNDRangeKernel(
  cl_command_queue command_queue,
  cl_kernel kernel,
  cl_uint work_dim, // 使用的dimension的维度
  const size_t* global_work_offset, //描述获取到的global_work_id的偏移值。比如5号PE要处理第11个数据,就要6个便宜
  const size_t* global_work_size, // 指定维度上的global work item的数量。global_work_size[0]就是一维,global_work_size[1]就是二维
  const size_t* local_work_size, //指定维度上的local work item的数量,
  cl_uint num_events_in_wait_list, //在这个命令执行前,需要等待的事件数量
  const cl_event* event_wait_list, //在这个命令执行前,需要等待的事件集合
  cl_event* event); // Event返回一个事件对象,该对象标识该读/写命令,可用于查询或排队等待该命令完成。
cl_int clEnqueueReadBuffer(
  cl_command_queue command_queue,
  cl_mem buffer,
  cl_bool blocking_read, // 是否阻塞读,也就是要等kernel执行完再读
  size_t offset, // 要读写内存的偏移
  size_t size, // 要读写的内存大小
  void* ptr, // 要读写的主机内存
  cl_uint num_events_in_wait_list, // 在这个命令执行前,需要等待的事件数量
  const cl_event* event_wait_list, // 在这个命令执行前,需要等待的事件集合
  cl_event* event); // Event返回一个事件对象,该对象标识该读/写命令,可用于查询或排队等待该命令完成。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值