我正在尝试学习 OpenCL,这很有趣,但学习曲线陡峭(至少对我而言)。
跟随本书:OpenCl in Action
我编写了一个简单的程序,它可以为我提供有关我拥有的 opencl 设备的信息,但仍然没有上下文,没有内核,什么都没有。
我定义了两个结构(来自一些在线博客的想法):
注意:请跳转到文件末尾的通知
设备描述
typedef struct DeviceDesc{
cl_device_id deviceID;
cl_device_type Type;
char* TypeString;
char* Name;
char* Ext;
cl_bool Available;
cl_ulong GlobalMemSize;
cl_ulong LocalMemSize;
cl_uint Clock;
cl_uint ComputeUnits;
} DeviceDesc;
平台描述
typedef struct PlatformDesc{
cl_platform_id pID;
char* pName;
char* pExt;
char* pVersion;
char* pVendor;
} PlatformDesc;
我还定义了两个枚举
PINFO
enum pINFO{
name = 0,
vendor = 1,
ext = 2,
profile = 3,
version = 4,
}pINFO;
DINFO
enum dINFO{
dname = 0, //char*
davail = 1, //clbool
dext = 2, //char*
dgmemsize = 3, //ulong
dlmemsize = 4, //ulong
dmaxclock = 5, //uint
dcompunits = 6,//uint
}dINFO;
我还定义了这些函数:
void cl_error_check(cl_int err,char* msg) {
if (!err==CL_SUCCESS) {
printf("%s\n",msg);
exit(1);
}
}
void cl_PFINFO(PlatformDesc* platform,enum pINFO itype,int i) {
size_t datasize;
char* data;
cl_int err;
//name = 0, //char*
//avail = 1, //clbool
//ext = 2, //char*
//gmemsize = 3, //ulong
//lmemsize = 4, //ulong
//maxclock = 5, //uint
//compunits = 6,//uint
switch(itype) {
case 0: //name
err = clGetPlatformInfo(platform[i].pID,CL_PLATFORM_NAME,0,NULL,&datasize);
cl_error_check(err,"Couldn't Obtain Plaform Name!");
data = (char*)malloc(sizeof(datasize));
clGetPlatformInfo(platform[i].pID,CL_PLATFORM_NAME,datasize,data,NULL);
platform[i].pName = data;
break;
case 1: //avail
err = clGetPlatformInfo(platform[i].pID,CL_PLATFORM_VENDOR,0,NULL,&datasize);
cl_error_check(err,"Couldn't Obtain Plaform Vendor!");
data = (char*)malloc(sizeof(datasize));
clGetPlatformInfo(platform[i].pID,CL_PLATFORM_VENDOR,datasize,data,NULL);
platform[i].pVendor = data;
break;
case 2: //ext
err = clGetPlatformInfo(platform[i].pID,CL_PLATFORM_EXTENSIONS,0,NULL,&datasize);
cl_error_check(err,"Couldn't Obtain Plaform Extensions!");
data = (char*)malloc(sizeof(datasize));
clGetPlatformInfo(platform[i].pID,CL_PLATFORM_EXTENSIONS,datasize,data,NULL);
platform[i].pExt = data;
break;
case 3: //globalmemorysize
break;
case 4: //localmemorysize
err = clGetPlatformInfo(platform[i].pID,CL_PLATFORM_VERSION,0,NULL,&datasize);
cl_error_check(err,"Couldn't Obtain Plaform Version!");
data = (char*)malloc(sizeof(datasize));
clGetPlatformInfo(platform[i].pID,CL_PLATFORM_VERSION,datasize,data,NULL);
platform[i].pVersion = data;
break;
break;
default:
printf("Unknown Platform Info Type! %d",itype);
exit(1);
}
}
void cl_DVINFO(DeviceDesc* dev,enum dINFO itype,int i) {
size_t datasize;
char* data;
cl_bool av;
cl_int err;
cl_ulong gm,lm;
cl_uint clock,units;
//name = 0, //char*
//avail = 1, //clbool
//ext = 2, //char*
//gmemsize = 3, //ulong
//lmemsize = 4, //ulong
//maxclock = 5, //uint
//compunits = 6,//uint
switch(itype) {
case 0: //name
err = clGetDeviceInfo(dev[i].deviceID,CL_DEVICE_NAME,0,NULL,&datasize);
cl_error_check(err,"Couldn't Obtain Device Name!");
data = (char*)malloc(sizeof(datasize));
clGetDeviceInfo(dev[i].deviceID,CL_DEVICE_NAME,datasize,data,NULL);
dev[i].Name = data;
printf("\nDevice Name: %s",dev[i].Name);
break;
case 1: //avail
err = clGetDeviceInfo(dev[i].deviceID,CL_DEVICE_AVAILABLE,sizeof(cl_bool),&av,NULL);
cl_error_check(err,"Couldn't Obtain Device Availability!");
dev[i].Available = av;
printf("\nDevice Available: %d",dev[i].Available);
break;
case 2: //ext
err = clGetDeviceInfo(dev[i].deviceID,CL_DEVICE_EXTENSIONS,0,NULL,&datasize);
cl_error_check(err,"Couldn't Obtain Device Extensions!");
data = (char*)malloc(sizeof(datasize));
clGetDeviceInfo(dev[i].deviceID,CL_DEVICE_EXTENSIONS,datasize,data,NULL);
dev[i].Ext = data;
break;
case 3: //globalmemorysize
err = clGetDeviceInfo(dev[i].deviceID,CL_DEVICE_GLOBAL_MEM_SIZE,sizeof(cl_ulong),&gm,NULL);
cl_error_check(err,"Couldn't Obtain Device Global Memory Size!");
dev[i].GlobalMemSize = gm;
printf("\nDevice Global Memory Size: %lu",dev[i].GlobalMemSize);
break;
case 4: //localmemorysize
err = clGetDeviceInfo(dev[i].deviceID,CL_DEVICE_LOCAL_MEM_SIZE,sizeof(cl_ulong),&lm,NULL);
cl_error_check(err,"Couldn't Obtain Device Local Memory Size!");
dev[i].LocalMemSize = lm;
printf("\nDevice Local Memory Size: %lu",dev[i].LocalMemSize);
break;
case 5: //Max Clock
err = clGetDeviceInfo(dev[i].deviceID,CL_DEVICE_MAX_CLOCK_FREQUENCY,sizeof(cl_uint),&clock,NULL);
cl_error_check(err,"Couldn't Obtain info on Device Max Clock Frequency!");
dev[i].Clock = clock;
printf("\nDevice Clock: %u",dev[i].Clock);
break;
case 6://Max Compte
err = clGetDeviceInfo(dev[i].deviceID,CL_DEVICE_MAX_COMPUTE_UNITS,sizeof(cl_uint),&units,NULL);
cl_error_check(err,"Couldn't Obtain info on Device Max Computing Units!");
dev[i].ComputeUnits = units;
printf("\nDevice Compute Units: %u",dev[i].ComputeUnits);
break;
default:
printf("Unknown Device Info Type! %d",itype);
exit(1);
}
}
我知道这很多,但是我的程序运行良好,直到我到达注释中标有 ==> 的代码部分,问题是有时,代码运行良好,有时在识别第二个 GPU 后崩溃,这是主要的
int main(int argc, char** argv) {
/*
OPEN CL INIT AND STUFF
*/
cl_platform_id platformID;
cl_device_id *CPUID,*GPUID;
cl_uint num_devices,addr_data,num_platforms = 1;
cl_uint num_CPU,num_GPU;
cl_int err, i;
char dname_data[48],dext_data[4096];
int k;
PlatformDesc* platform = (PlatformDesc*)malloc(sizeof(PlatformDesc));
DeviceDesc* CPUS = NULL;
DeviceDesc* GPUS = NULL;
err = clGetPlatformIDs(num_platforms,&platformID,NULL);
cl_error_check(err,"Couldn't find any platforms!");
platform[0].pID = platformID;
//Get CPUs
err = clGetDeviceIDs(platform[0].pID,CL_DEVICE_TYPE_CPU,NULL,NULL,&num_CPU);
cl_error_check(err,"Error in finding CPUS!");
CPUS = (DeviceDesc*)malloc(num_CPU*sizeof(DeviceDesc));
CPUID = (cl_device_id*)malloc(num_CPU*sizeof(cl_device_id));
err = clGetDeviceIDs(platform[0].pID,CL_DEVICE_TYPE_CPU,num_CPU,CPUID,NULL);\
cl_error_check(err,"Error in Getting CPUS!");
for (k = 0;k<num_CPU;k++) {
CPUS[k].deviceID = CPUID[k];
CPUS[k].Type = CL_DEVICE_TYPE_CPU;
CPUS[k].TypeString = "CPU";
//get device info
int l;
for (l=0;l<7;l++)
cl_DVINFO(CPUS,l,k);
}
//Get GPUs
err = clGetDeviceIDs(platform[0].pID,CL_DEVICE_TYPE_GPU,NULL,NULL,&num_GPU);
cl_error_check(err,"Error in finding GPUS!");
GPUS = (DeviceDesc*)malloc(num_GPU*sizeof(DeviceDesc));
GPUID = (cl_device_id*)malloc(num_GPU*sizeof(cl_device_id));
err = clGetDeviceIDs(platform[0].pID,CL_DEVICE_TYPE_GPU,num_GPU,GPUID,NULL);\
cl_error_check(err,"Error in Getting GPUS!");
for (k = 0;k<num_GPU;k++) {
//==> Most of the crashing occurs here... if they occur
GPUS[k].deviceID = GPUID[k];
GPUS[k].Type = CL_DEVICE_TYPE_GPU;
GPUS[k].TypeString = "GPU";
int l;
for (l=0;l<7;l++)
cl_DVINFO(GPUS,l,k); //Here, i am getting the info "L" for the GPU K
}
//Ok Now get Platform info
cl_PFINFO(platform,name,0);
cl_PFINFO(platform,vendor,0);
cl_PFINFO(platform,ext,0);
cl_PFINFO(platform,version,0);
scanf("%d",&k); //THIS SCANF is just to see if it reaches this part or not, useless
//CLEANUP
free(GPUID);
free(CPUID);
free(CPUS);
free(GPUS);
return 0;
}
这是我从我的机器获得的示例输出
Device Name: AMD FX(tm)-8120 Eight-Core Processor
Device Available: 1
Device Global Memory Size: 2147483648
Device Local Memory Size: 32768
Device Clock: 4100
Device Compute Units: 8
Device Name: Tahiti
Device Available: 1
Device Global Memory Size: 2147483648
Device Local Memory Size: 32768
Device Clock: 950
Device Compute Units: 28
Device Name: Tahiti
Device Available: 1
Device Global Memory Size: 2147483648
Device Local Memory Size: 32768
Device Clock: 950
Device Compute Units: 28
Process returned -1073741819 (0xC0000005) execution time : 2.206 s
Press any key to continue.
有时没有确定第二个大溪地。无论如何,我得到一个 0xC0000005 (我认为这是访问冲突,又名与指针有关)
我的问题是,我哪里出错了:)。我的意思是如果我不能这样做,我将如何处理内核:P
注意
由于请求,我将发布代码失败的部分:
代码在这里失败
for (k = 0;k<num_CPU;k++) {
CPUS[k].deviceID = CPUID[k];
CPUS[k].Type = CL_DEVICE_TYPE_CPU;
CPUS[k].TypeString = "CPU";
//get device info
int l;
for (l=0;l<7;l++)
cl_DVINFO(CPUS,l,k);
}