2014-12-06 2 views
0

Я пытаюсь создать настраиваемый класс вокруг оболочки OpenCL C++, чтобы получить определенную информацию от доступных устройств. Например, получите количество доступных графических процессоров, процессоров и т. Д. На платформе. Чтобы уменьшить код, который я решил реализовать частные функции шаблона, как показано ниже:приватная функция шаблона C++ в обычном классе - OpenCL

//Devices.hpp 
class Devices 
{ 
public: 
    Devices(const cl::Platform& inputPlatform) 
    { 
     inputPlatform.getDevices(CL_DEVICE_TYPE_ALL, &availableDevices); 
    } 
    cl_int getTotalNumberOfDevices() 
    { 
     return availableDevices.size(); 
    } 
    cl_int getTotalNumberOfGPUs() 
    { 
     return countDevicesWithSpecificProperty(CL_DEVICE_TYPE, CL_DEVICE_TYPE_GPU); 
    } 
private: 
    std::vector<cl::Device> availableDevices; 

    template <typename T> 
    cl_int countDevicesWithSpecificProperty(
     const cl_device_info& deviceInfo, 
     const T& searchPropertyValue) 
    { 
     cl_int totalNumberOfDevices = getTotalNumberOfDevices(); 

     T response; 
     cl_int count = 0; 
     for (cl_int i = 0; i < totalNumberOfDevices; ++i) 
     { 
      try 
      { 
       availableDevices.at(i).getInfo(deviceInfo, &response); 
      } 
      catch (cl::Error e) 
      { 
       return e.err(); 
      } 
      if (response == searchPropertyValue) ++count; 
     } 

     return count; 
    } 
}; 

Хотя код компилируется правильно, GetInfo бросает ошибку CL_INVALID_VALUE. Когда я реализовал один и тот же код с использованием обычной функции (вместо шаблона), код работает нормально:

//Devices.hpp 
class Devices 
{ 
public: 
    Devices(const cl::Platform& inputPlatform) 
    { 
     inputPlatform.getDevices(CL_DEVICE_TYPE_ALL, &availableDevices); 
    } 
    cl_int getTotalNumberOfDevices() 
    { 
     return availableDevices.size(); 
    } 
    cl_int getTotalNumberOfGPUs() 
    { 
     return countDevicesWithSpecificProperty(CL_DEVICE_TYPE, CL_DEVICE_TYPE_GPU); 
    } 
private: 
    std::vector<cl::Device> availableDevices; 

    cl_int countDevicesWithSpecificProperty 
    (const cl_device_info& deviceInfo, 
    const cl_device_type& searchPropertyValue) 
    { 
     cl_int totalNumberOfDevices = getTotalNumberOfDevices(); 

     cl_device_type response; 
     cl_int count = 0; 
     for (cl_int i = 0; i < totalNumberOfDevices; ++i) 
     { 
      try 
      { 
       availableDevices.at(i).getInfo(deviceInfo, &response); 
      } 
      catch (cl::Error e) 
      { 
       return e.err(); 
      } 

      if (response == searchPropertyValue) ++count; 
     } 

     return count; 
    } 
}; 

Любые мысли?

PS: метод вызывается следующим образом:

//main.cpp 
#define __CL_ENABLE_EXCEPTIONS 

#include <iostream> 
#include <vector> 

#include <CL/cl.hpp> 

#include "Devices.hpp" 

int main() 
{ 
    try 
    { 
     std::vector<cl::Platform> availablePlatforms; 
     cl::Platform::get(&availablePlatforms); 
     Devices d(availablePlatforms[0]); 

     std::cout << d.getTotalNumberOfGPUs() << std::endl; 

    } 
    catch (cl::Error e) 
    { 
     std::cout << e.what() << std::endl << e.err() << std::endl; 
    } 
    return 0; 
} 
+0

почему вы используете cl_uint Фори в одной петле и cl_int в другой. это может быть причиной. в противном случае также сообщите, как вы вызываете метод. также: зачем использовать шаблон здесь? – marc

+0

Извините за это. Это была опечатка при передаче кода (я добавил блок try-catch, и поскольку err() является cl_int, мне пришлось заменить cl_uint на cl_int, но я, очевидно, пропустил это ...). Чтобы вызвать метод, я использую простой код C++, где в main() я включил следующее: \t \t std :: vector availablePlatforms; \t \t cl :: Платформа :: get (& availablePlatforms); \t \t Устройства d (availablePlatforms [0]); \t \t std :: cout << d.getTotalNumberOfGPUs() << std :: endl; – thanasis

ответ

1

Проблема в том, что ваша переменная response не имеет нужного типа в вашей шаблонизированной версии. Это связано с тем, что вы передаете CL_DEVICE_TYPE_GPU в шаблонный параметр, который является макросом препроцессора, и поэтому не обязательно будет иметь правильный тип, необходимый для информационного запроса устройства.

Одним из решений является явно привести шаблонный параметр, чтобы убедиться, что он имеет правильный тип:

return countDevicesWithSpecificProperty(CL_DEVICE_TYPE, (cl_device_type)CL_DEVICE_TYPE_GPU); 
0

Проверьте ассемблерный листинг для обоих случаев. Должно быть какое-то различие в том, что генерирует компилятор.

Смежные вопросы