디바이스 별로 고유한 확장 기능을 부여할 수 있다.
이런 기능이 추가되어 있는지 확인을 한다.
추가되는 함수는 아래에 표시되어 있다.
void displayDeviceInfo( cl_platform_id id ,
cl_device_type dev_type)
......
displayDeviceDetails( devices[i], CL_DEVICE_EXTENSIONS, "CL_DEVICE_EXTENSIONS" );
.....
void displayDeviceDetails( cl_device_id id,
cl_device_info param_name,
const char * paramNameAsStr)
...
switch(param_name)
{
......
break;
case CL_DEVICE_EXTENSIONS : {
// beware of buffer overflow; alternatively use the OpenCL C++ bindings
char* extension_info[4096];
error = clGetDeviceInfo( id, CL_DEVICE_EXTENSIONS, sizeof(extension_info),
extension_info, NULL);
printf("\tSupported extensions: %s\n", extension_info);
}break;
}
....
확장에 대한 정보를 확인하기 위해서 CL_DEVICE_EXTENSONS를 확인하면 된다.
세부 정보에서 해당 정보를 프린트하도록 한다.
완성된 코드와 실행 결과는 아래와 같다.
//
// main.cpp
// TestOpenCL
//
// Created by freegear on 2014. 2. 8..
// Copyright (c) 2014년 freegear. All rights reserved.
//
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#ifdef __APPLE__
# include <OpenCL/opencl.h>
#else
# include <CL/cl.h>
#endif
//Function proto type
void displayDeviceDetails(cl_device_id id ,
cl_device_info param_name,
const char * paramNameAsStr);
void displayDeviceInfo( cl_platform_id id ,
cl_device_type dev_type)
{
/* OpenCL 1.1 device type */
cl_int error = 0 ;
cl_uint numOfDevices = 0 ;
/* Determine how many devices are connected to your platform */
error = clGetDeviceIDs(id, dev_type, 0, NULL, &numOfDevices);
if( error != CL_SUCCESS){
perror("Unable to obtain any OpenCL compliant device info");
exit(1);
}
cl_device_id * devices = (cl_device_id*)alloca(sizeof(cl_device_id) * numOfDevices);
/* Load the information about your devices into the variable 'devices' */
error = clGetDeviceIDs(id, dev_type, numOfDevices, devices, NULL);
if (error != CL_SUCCESS)
{
perror("Unable to obtain any OpenCL compliant device info");
exit(1);
}
printf("Numnber of detected OpenCL devices %d\n", numOfDevices);
/* we attempt to retrieve some information about the devices */
for( int i = 0 ; i < numOfDevices ; ++i)
{
displayDeviceDetails(devices[i], CL_DEVICE_TYPE, "CL_DEVICE_TYPE");
displayDeviceDetails(devices[i], CL_DEVICE_VENDOR_ID, "CL_DEVICE_VENDOR_ID");
displayDeviceDetails(devices[i], CL_DEVICE_MAX_COMPUTE_UNITS, "CL_DEVICE_MAX_COMPUTE_UNITS");
displayDeviceDetails(devices[i], CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, "CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS");
displayDeviceDetails(devices[i], CL_DEVICE_MAX_WORK_ITEM_SIZES, "CL_DEVICE_MAX_WORK_ITEM_SIZES");
displayDeviceDetails(devices[i], CL_DEVICE_MAX_WORK_GROUP_SIZE, "CL_DEVICE_MAX_WORK_GROUP_SIZE");
displayDeviceDetails( devices[i], CL_DEVICE_EXTENSIONS, "CL_DEVICE_EXTENSIONS" );
}
}
void displayDeviceDetails( cl_device_id id,
cl_device_info param_name,
const char * paramNameAsStr)
{
cl_int error = 0 ;
size_t paramSize = 0 ;
error = clGetDeviceInfo( id ,param_name, 0 , NULL, ¶mSize);
if(error != CL_SUCCESS)
{
perror("Unable to obtain device info for param");
return;
}
/*
The cl_device_info are preporcessor directives define in cl.h
*/
switch(param_name)
{
case CL_DEVICE_TYPE :
{
cl_device_type * devType = (cl_device_type*)alloca(sizeof(cl_device_type)*paramSize);
error = clGetDeviceInfo(id, param_name, paramSize, devType, NULL);
if(error != CL_SUCCESS)
{
perror("Unable to optain device info for param\n");
return;
}
switch( *devType)
{
case CL_DEVICE_TYPE_CPU : printf("CPU Detected \n"); break;
case CL_DEVICE_TYPE_GPU : printf("GPU Detected \n"); break;
case CL_DEVICE_TYPE_ACCELERATOR : printf("Accelerator detected\n");break;
case CL_DEVICE_TYPE_DEFAULT : printf("default detected \n"); break;
}
break;
}
case CL_DEVICE_VENDOR_ID :
case CL_DEVICE_MAX_COMPUTE_UNITS :
case CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS : {
cl_uint* ret = (cl_uint*) alloca(sizeof(cl_uint) * paramSize);
error = clGetDeviceInfo( id, param_name, paramSize, ret, NULL );
if (error != CL_SUCCESS ) {
perror("Unable to obtain device info for param\n");
return;
}
switch (param_name) {
case CL_DEVICE_VENDOR_ID: printf("\tVENDOR ID: 0x%x\n", *ret); break;
case CL_DEVICE_MAX_COMPUTE_UNITS: printf("\tMaximum number of parallel compute units: %d\n", *ret); break;
case CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS: printf("\tMaximum dimensions for global/local work-item IDs: %d\n", *ret); break;
}
}
break;
case CL_DEVICE_MAX_WORK_ITEM_SIZES :
{
cl_uint maxWIDimensions;
size_t* ret = (size_t*) alloca(sizeof(size_t) * paramSize);
error = clGetDeviceInfo( id, param_name, paramSize, ret, NULL );
error = clGetDeviceInfo( id, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, sizeof(cl_uint), &maxWIDimensions, NULL );
if (error != CL_SUCCESS ) {
perror("Unable to obtain device info for param\n");
return;
}
printf("\tMaximum number of work-items in each dimension: ( ");
for(cl_int i =0; i < maxWIDimensions; ++i ) {
printf("%d ", (int)ret[i]);
}
printf(" )\n");
}break;
case CL_DEVICE_MAX_WORK_GROUP_SIZE :
{
size_t* ret = (size_t*) alloca(sizeof(size_t) * paramSize);
error = clGetDeviceInfo( id, param_name, paramSize, ret, NULL );
if (error != CL_SUCCESS ) {
perror("Unable to obtain device info for param\n");
return;
}
printf("\tMaximum number of work-items in a work-group: %d\n", (int)*ret);
}
break;
case CL_DEVICE_NAME :
case CL_DEVICE_VENDOR :
{
char data[48];
error = clGetDeviceInfo( id, param_name, paramSize, data, NULL );
if (error != CL_SUCCESS ) {
perror("Unable to obtain device name/vendor info for param\n");
return;
}
switch (param_name) {
case CL_DEVICE_NAME : printf("\tDevice name is %s\n", data);break;
case CL_DEVICE_VENDOR : printf("\tDevice vendor is %s\n", data);break;
}
}
break;
case CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE: {
cl_uint* size = (cl_uint*) alloca(sizeof(cl_uint) * paramSize);
error = clGetDeviceInfo( id, param_name, paramSize, size, NULL );
if (error != CL_SUCCESS ) {
perror("Unable to obtain device name/vendor info for param\n");
return;
}
printf("\tDevice global cacheline size: %d bytes\n", (*size)); break;
} break;
case CL_DEVICE_GLOBAL_MEM_SIZE:
case CL_DEVICE_MAX_MEM_ALLOC_SIZE:
{
cl_ulong* size = (cl_ulong*) alloca(sizeof(cl_ulong) * paramSize);
error = clGetDeviceInfo( id, param_name, paramSize, size, NULL );
if (error != CL_SUCCESS ) {
perror("Unable to obtain device name/vendor info for param\n");
return;
}
switch (param_name) {
case CL_DEVICE_GLOBAL_MEM_SIZE: printf("\tDevice global mem: %ld mega-bytes\n", (*size)>>20); break;
case CL_DEVICE_MAX_MEM_ALLOC_SIZE: printf("\tDevice max memory allocation: %ld mega-bytes\n", (*size)>>20); break;
}
}
break;
case CL_DEVICE_EXTENSIONS : {
// beware of buffer overflow; alternatively use the OpenCL C++ bindings
char* extension_info[4096];
error = clGetDeviceInfo( id, CL_DEVICE_EXTENSIONS, sizeof(extension_info), extension_info, NULL);
printf("\tSupported extensions: %s\n", extension_info);
}break;
}//end of switch(param_name
}// end of displayDeviceDetailes
void displayPlatformInfo(
cl_platform_id id ,
cl_platform_info param_name,
const char * paramNameAsStr
)
{
cl_int error = 0 ;
size_t paramSize = 0 ;
error = clGetPlatformInfo(
id,
param_name,
0,
NULL,
¶mSize
);
char * moreInfo = (char *) alloca(sizeof(char)*paramSize);
error = clGetPlatformInfo(
id, /* The platform ID returned by clGetPlatformIDs or can be NULL.
If platform is NULL, the behavior is implementation-defined.*/
param_name, /* An enumeration constant that identifies the platform
information being queried. It can be one of the following values
as specified in the table below. */
paramSize, /* Specifies the size in bytes of memory pointed to by param_value.
This size in bytes must be greater than or equal to size of return type
specified in the table below. */
moreInfo, /* A pointer to memory location where appropriate values for a given
param_value will be returned. Acceptable param_value values are listed in
the table below. If param_value is NULL, it is ignored.*/
NULL /* Returns the actual size in bytes of data being queried by param_value.
If param_value_size_ret is NULL, it is ignored */
);
if( error != CL_SUCCESS)
{
if ( error == CL_INVALID_PLATFORM)
perror("Error CL_INVALID_PLATFORM");
else if (error == CL_INVALID_VALUE)
perror("Error CL_INVALID_VALUE");
else
perror("Unable to find any OpenCL platform information");
return ;
}
printf("%s : %s\n" , paramNameAsStr, moreInfo);
} // end of displayPlatformInfo
int main(int argc, const char * argv[])
{
// OpenCL 1.2 Data struction
cl_platform_id * platforms ;
/* OpenCL 1.1 scalar data types */
cl_uint numOfPlatforms ;
cl_int error ;
/*
Get the number of platforms
Remember that for each vendor's SDK installed on the computer,
the number of available platform also increased.
*/
error = clGetPlatformIDs(0, /*
The number of cl_platform_id entries that can be added to platforms.
If platforms is not NULL, the num_entries must be greater than zero.
*/
NULL, /* Returns a list of OpenCL platforms found.
The cl_platform_id values returned in platforms can be used to identify
a specific OpenCL platform. If platforms argument is NULL,
this argument is ignored.
The number of OpenCL platforms returned is the mininum of the value
specified by num_entries or the number of OpenCL platforms available. */
&numOfPlatforms
/* Returns the number of OpenCL platforms available.
If num_platforms is NULL, this argument is ignored. */
);
if ( error < 0)
{
perror("Unable to find any OpenCL platforms");
exit(1);
}
// allocate memory for the number of installed platforms
// alloca(....) occupies some stack space but is
// automatically freed on return
platforms = (cl_platform_id*) alloca(sizeof(cl_platform_id)*numOfPlatforms);
printf("Number of OpenCL platforms found : %d\n", numOfPlatforms);
error = clGetPlatformIDs(numOfPlatforms, /*
The number of cl_platform_id entries that can be added to platforms.
If platforms is not NULL, the num_entries must be greater than zero.
*/
platforms, /* Returns a list of OpenCL platforms found.
The cl_platform_id values returned in platforms can be used to identify
a specific OpenCL platform. If platforms argument is NULL,
this argument is ignored.
The number of OpenCL platforms returned is the mininum of the value
specified by num_entries or the number of OpenCL platforms available. */
NULL
/* Returns the number of OpenCL platforms available.
If num_platforms is NULL, this argument is ignored. */
);
if ( error < 0)
{
perror("Unable to find any OpenCL platforms");
exit(1);
}
// We invoke the API 'clPlatformInfo' twice for each
// parameter we are trying to extract
// and we use the return value to create temporary data
// structure (on the stack) to store
// the returned information ot the second invocation.
for( cl_uint i = 0 ; i < numOfPlatforms ; ++i)
{
displayPlatformInfo( platforms[i], CL_PLATFORM_PROFILE , "CL_PLATFORM_PROFILE");
displayPlatformInfo( platforms[i], CL_PLATFORM_VERSION , "CL_PLATFORM_VERSION");
displayPlatformInfo( platforms[i], CL_PLATFORM_NAME , "CL_PLATFORM_NAME");
displayPlatformInfo( platforms[i], CL_PLATFORM_VENDOR , "CL_PLATFORM_VENDOR");
displayPlatformInfo( platforms[i], CL_PLATFORM_EXTENSIONS , "CL_PLATFORM_EXTENSIONS");
// Assume that we don't know how many devices are OpenCL compliant, we locate everything !
displayDeviceInfo( platforms[i], CL_DEVICE_TYPE_ALL );
}
return 0;
}
실행 결과
Number of OpenCL platforms found : 1
CL_PLATFORM_PROFILE : FULL_PROFILE
CL_PLATFORM_VERSION : OpenCL 1.2 (Aug 24 2013 21:03:27)
CL_PLATFORM_NAME : Apple
CL_PLATFORM_VENDOR : Apple
CL_PLATFORM_EXTENSIONS : cl_APPLE_SetMemObjectDestructor cl_APPLE_ContextLoggingFunctions cl_APPLE_clut cl_APPLE_query_kernel_names cl_APPLE_gl_sharing cl_khr_gl_event
Numnber of detected OpenCL devices 3
CPU Detected
VENDOR ID: 0xffffffff
Maximum number of parallel compute units: 8
Maximum dimensions for global/local work-item IDs: 3
Maximum number of work-items in each dimension: ( 1024 1 1 )
Maximum number of work-items in a work-group: 1024
Supported extensions: cl_APPLE_SetMemObjectDestructor cl_APPLE_ContextLoggingFunctions cl_APPLE_clut cl_APPLE_query_kernel_names cl_APPLE_gl_sharing cl_khr_gl_event cl_khr_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_byte_addressable_store cl_khr_int64_base_atomics cl_khr_int64_extended_atomics cl_khr_3d_image_writes cl_khr_image2d_from_buffer cl_APPLE_fp64_basic_ops cl_APPLE_fixed_alpha_channel_orders cl_APPLE_biased_fixed_point_image_formats cl_APPLE_command_queue_priority
GPU Detected
VENDOR ID: 0x1022700
Maximum number of parallel compute units: 2
Maximum dimensions for global/local work-item IDs: 3
Maximum number of work-items in each dimension: ( 1024 1024 64 )
Maximum number of work-items in a work-group: 1024
Supported extensions: cl_APPLE_SetMemObjectDestructor cl_APPLE_ContextLoggingFunctions cl_APPLE_clut cl_APPLE_query_kernel_names cl_APPLE_gl_sharing cl_khr_gl_event cl_khr_byte_addressable_store 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_APPLE_fp64_basic_ops cl_khr_fp64 cl_khr_3d_image_writes cl_khr_depth_images cl_khr_gl_depth_images cl_khr_gl_msaa_sharing cl_khr_image2d_from_buffer
GPU Detected
VENDOR ID: 0x1024400
Maximum number of parallel compute units: 16
Maximum dimensions for global/local work-item IDs: 3
Maximum number of work-items in each dimension: ( 512 512 512 )
Maximum number of work-items in a work-group: 512
Supported extensions: cl_APPLE_SetMemObjectDestructor cl_APPLE_ContextLoggingFunctions cl_APPLE_clut cl_APPLE_query_kernel_names cl_APPLE_gl_sharing cl_khr_gl_event 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_byte_addressable_store cl_khr_image2d_from_buffer cl_khr_gl_depth_images cl_khr_depth_images
Program ended with exit code: 0
위에서 나온 용어에 대해서 다음페이지에서 설명한다.