使用clGetDeviceInfo从内存中读取访问冲突

时间:2017-04-23 14:02:33

标签: c++ opencl

我收到“有时”访问违规错误;该程序有时工作并吐出设备名称和类型,有时它只会引发访问冲突异常。

我程序的输出(来自printf)如下:

  

不必要的东西

     

检测到的OpenCL设备数量:2

所以显然我正在检测每个平台的两个设备(参见代码中的for循环)。

该数字由 getDeviceInfo 函数给出并存储在虚拟变量中,因此该函数可能存在问题。

我在调试期间注意到了 getDeviceInfo 返回

  

0x0000000d49eff270 {0x000001f1ff027af0} _cl_device_id **

我猜第一位(0x0000000d49eff270)是设备数组开头的内存位置。 但是当我在这行中访问我的设备数组时

cl_device_id device = devices[i]; //see me in the main inside the second for loop

我得到这个值(对于设备[i]和设备):

  

0xcccccccccccccccc {...} _cl_device_id *

无论如何,程序继续尝试使用 displayDeviceDetails 函数获取设备信息,并且如前所述, clGetDeviceInfo 上的访问冲突失败。

发生什么事了?为什么它有时也能正常工作,如果有什么不对的话。它不应该工作吗?

我附上相关的源代码:

getDeviceInfo

cl_device_id* getDeviceInfo(cl_platform_id platform_id, cl_device_type device_type, cl_uint &numOfDev)
 {
    cl_int error = 0;
    cl_uint numberOfDevices = 0;

    /* Determine how many devices are in the platform */
    error = clGetDeviceIDs(platform_id, device_type, 0, NULL, &numberOfDevices);
    if (checkCLError(error, "Unable to obtain any OpenCL device info")) 
    {
        exit(1);
    }

    numOfDev = numberOfDevices;

    /* allocate memory for the devices array (pointer) */
    cl_device_id* devices = (cl_device_id*)alloca(sizeof(cl_device_id) * numberOfDevices);

    /* Load device information into array devices */
    error = clGetDeviceIDs(platform_id, device_type, numberOfDevices, devices, NULL);

    if (checkCLError(error, "Unable to obtain device info")) 
    {
        exit(1);
    }

    printf("Number of detected OpenCL devices: %d\n", numberOfDevices);
    return devices;
}

displayDeviceDetails:

void displayDeviceDetails(cl_device_id dev_id, cl_device_info param_name, const     char* paramNameAsStr)
{
    cl_int error = 0;
    size_t paramSize = 0;

    /* Get Device Info size */
    error = clGetDeviceInfo(dev_id, param_name, 0, NULL, &paramSize);
    if (checkCLError(error, "Unable to obtain device info")) 
    {
        return;
    }

    switch (param_name)
    {
    case CL_DEVICE_TYPE:
        {
        cl_device_type* devType = (cl_device_type*)alloca(sizeof(cl_device_type)* paramSize);
        error = clGetDeviceInfo(dev_id, param_name, paramSize, devType, NULL);
        if (checkCLError(error, "Unable to obtain a specific device info"))
        {
            return;
        }
        switch (*devType)
        {
        case CL_DEVICE_TYPE_CPU:
            printf("\tCPU Detected\n");
            break;
        case CL_DEVICE_TYPE_GPU:
            printf("\tGPU Detected\n");
            break;
        default:
            printf("\tOther stuff Detected\n");
        }
        break;
        }

    case CL_DEVICE_NAME:
        {
        char* devName = (char*)alloca(sizeof(CL_DEVICE_NAME)*paramSize);
        error = clGetDeviceInfo(dev_id, param_name, paramSize, devName, NULL);
        printf("\tName: %s\n", devName);
        break;
        }
    }
}

主要

int main() {

    cl_platform_id* platforms;
    cl_uint numOfPlatforms;
    cl_int error;

    error = clGetPlatformIDs(0, NULL, &numOfPlatforms);
    if (checkCLError(error, "Unable to find OpenCL Plaftorms"))
    {
        exit(1);
    }
    printf("Number of OpenCL platform found: %d\n", numOfPlatforms);

    platforms = (cl_platform_id*)alloca(sizeof(cl_platform_id)*        numOfPlatforms);

    error = clGetPlatformIDs(numOfPlatforms, platforms, NULL);  // This line   initializes ""something"". Delete and u will get access violation

    for (cl_uint i = 0; i < numOfPlatforms; ++i) {
        printf("\n--------------------\nThe %d th platform\n-----------------    ---\n",i+1);

        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");

        cl_uint numOfDevices = 0;
        cl_device_id* devices = getDeviceInfo(platforms[i], CL_DEVICE_TYPE_ALL, numOfDevices);

        for (cl_uint i = 0; i < numOfDevices; ++i) 
        {
            printf("\tDevice (%d) Information\n\t----------------------\n",i);

            cl_device_id device = devices[i];
            displayDeviceDetails(device, CL_DEVICE_NAME, "CL_DEVICE_NAME");
            displayDeviceDetails(device, CL_DEVICE_TYPE, "CL_DEVICE_TYPE");
        }
     }
    return 0;
}

1 个答案:

答案 0 :(得分:2)

这是因为你正在使用alloca()。不要那么做! alloca()函数在调用者的堆栈帧中分配空间的大小字节,然后返回(这会破坏堆栈帧)。