5 Replies Latest reply on Mar 1, 2011 2:39 AM by Otterz

    Best way to select only devices with double precision support

    Otterz

      Hi,

      Is there a way to request a context with only devices that support double precision? I have been looking at cl_context_properties, but I don't get it.

      The way I am currently doing it, is to request a GPU context, then iterating through all devices and doing a string comparison on the tokens from

      getInfo<CL_DEVICE_EXTENSIONS>()

      And I compare against( cl_khr_fp64 or cl_amd_fp64) to retain the device (otherwise I pop it off).

      It seems like there should be an easier way to do this.

       

      Thanks !

        • Best way to select only devices with double precision support
          nou

          there is. just request all devices from platform. then query extansion list and check double support.

          after that create context.

          cl_uint num_entries; cl_int err_code = clGetDeviceIDs(platform_id, type, 0, NULL, &num_entries); cl_device_id devices[num_entries]; clGetDeviceIDs(platform_id, type, num_entries, devices, NULL);

            • Best way to select only devices with double precision support
              Otterz

              That seems to be essentially the same thing as I am doing (or am I misunderstanding you).

              It is just you query the platform for all devices of some type, then iterate through those devices. Then create the context. In my case, I create the context, retrieve the devices from the context, and iterate through them.

              // Create an OpenCL context cl_context_properties cprops[3] = {CL_CONTEXT_PLATFORM, (cl_context_properties)(platformList[0])(), 0}; cl::Context context( CL_DEVICE_TYPE_GPU, cprops, &contextCallback, NULL, &err); // List of available devices std::vector< cl::Device > devices; // populate list by querying the CPU context devices = context.getInfo<CL_CONTEXT_DEVICES>(); checkErr( devices.size() > 0 ? CL_SUCCESS : -1, "devices.size() > 0"); for(int i = (int) devices.size()-1; i >= 0; i--){ if(!not having double extension){ // Removing Device devices.pop_back(); } }

                • Best way to select only devices with double precision support
                  Otterz

                  Okay, I get it ><

                  I didn't realize there was a constructor for a context that took a set of devices. Thanks!

                    • Best way to select only devices with double precision support
                      himanshu.gautam

                      hi otterz,

                      Can you please explain the solution you found out. I didn't get the last post.

                        • Best way to select only devices with double precision support
                          Otterz

                          Yes my reply was fairly pointless. What the nou was pointing out is that I can query a platform for all devices, sort through each platform's devices and select only devices that meet my requirements. Then I can create the context using those devices.

                          I was doing it backwards. I was creating a context with all GPU devices, getting the devices from the context, and then iterating through those devices and selecting only those that I wanted to use. But his way is better.

                          It is still kinda messy. It would be nice to be able to query the driver with a list of key/value pairs indicating what devices you are interested in, and have it return only those devices.

                          e.g,

                          device.getIds( {Device_Type, GPU | CPU, CL_device_extension, cl_amd_f64 | cl_khr_frp4, Max_global_mem, 512000 }, &platformList )

                          The motivation for this is because one of the systems I test on contains an Nvidia Tesla as well as a low end Quadro. The quadro is the display card, and the Fermi is dedicated for compute. But apparently the quadro is modern enough to support OpenCL so it shows up in the list. (Only 1.0 support and no doubles)

                          I've attached my messy code, it is part of a C++ class, so some of the variables appear magically since they are class members.

                          void OpenCLAlgorithm::init_opencl_gpu(bool only64bit){ cl_int err; _hasGPU = false; std::vector<cl::Device> valid_devices; std::vector<cl_context_properties> cprops; std::vector<cl::Device>::iterator it; std::vector<cl::Platform> platformList; // Obtain a list of OpenCL platforms cl::Platform::get(&platformList); // Check for error checkErr(platformList.size() != 0 ? CL_SUCCESS : -1, "cl::Platform::get"); for(int i=0; i < platformList.size(); i++){ std::vector<cl::Device> devices; err = platformList[i].getDevices(CL_DEVICE_TYPE_GPU, &devices); //checkErr(err, "init_gpu: Platform::getDevices()", false); if(devices.size() == 0){ log_info("Platform: " + platformList[i].getInfo<CL_PLATFORM_NAME>() + " has no GPU devices" ); continue; } // Iterate through all devices for this platform and check if they support double for(it = devices.begin(); it != devices.end(); ){ std::string extensions = (*it).getInfo<CL_DEVICE_EXTENSIONS>(&err); if(only64bit){ // If the string does not contain the 64bit extension, erase this device if( extensions.find("cl_khr_fp64") == std::string::npos && extensions.find("cl_amd_fp64") == std::string::npos ) it = devices.erase(it); else it++; }else{ // If not requiring double, any GPU device will do it++; } } // If no devices are left, then this platform contains no GPUs we can use if(devices.size() == 0 && only64bit){ log_info("Platform: " + platformList[i].getInfo<CL_PLATFORM_NAME>() + " has no GPUs that support 64bit arithmetic" ); } // If atleast one device remains, they will all be 64bit compliant (if only64bit == true), // or OpenCL capable devices else if(devices.size() > 0){ // Print some information, and save this platforms devices, as well as this platforms properties for(it = devices.begin(); it != devices.end(); it++){ if(only64bit) log_info("Platform: " + platformList[i].getInfo<CL_PLATFORM_NAME>() + " contains device '" + (*it).getInfo<CL_DEVICE_NAME>() + "' which supports double precision"); else log_info("Platform: " + platformList[i].getInfo<CL_PLATFORM_NAME>() + " contains device '" + (*it).getInfo<CL_DEVICE_NAME>() + "'"); valid_devices.push_back((*it)); } // These properties are needed to create a context cprops.push_back(CL_CONTEXT_PLATFORM); cprops.push_back((cl_context_properties) devices.front().getInfo<CL_DEVICE_PLATFORM>()); } } // end of platformlist loop // if size is greater than zero, then atleast one GPU met our requirements from all platforms // attempt to create a context with these devices if(valid_devices.size() > 0){ _hasGPU = true; // cprops must end in 0 cprops.push_back(0); gpu_context = cl::Context( valid_devices, &cprops[0], &contextCallback, NULL, &err); // false as the last argument causes checkErr to not die checkErr(err, "init_gpu(): Context::Context()", false); // If the creation failed for any reason, checkErr will print a message // And this flag indicates no GPUs if(err != CL_SUCCESS) _hasGPU = false; }else{ // There were no devices in all platforms that met our requirements _hasGPU = false; } }