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

Access violation reading from memory using clGetDeviceInfo

我收到“有时”访问冲突错误;该程序有时会运行并吐出设备名称和类型,而其他时候它只会抛出访问冲突异常。

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

unnecessary stuff

Number of detected OpenCL devices: 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;
}

显示设备详细信息:

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;
}

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