2013-04-06 16 views
5

Sto cercando di utilizzare l'OpenCL C++ API wrapper per il seguente programma:OpenCL 1.2 C++ wrapper - undefined reference to clReleaseDevice

#define __CL_ENABLE_EXCEPTIONS 


#include <CL/cl.hpp> 
#include <cstdio> 
#include <cstdlib> 
#include <iostream> 

const char helloStr [] = "__kernel void " 
          "hello(void) " 
          "{ " 
          " " 
          "} "; 

int 
main(void) 
{ 
    cl_int err = CL_SUCCESS; 
    try { 

     std::vector<cl::Platform> platforms; 
     cl::Platform::get(&platforms); 
     if (platforms.size() == 0) { 
      std::cout << "Platform size 0\n"; 
      return -1; 
     } 

     cl_context_properties properties[] = 
     { CL_CONTEXT_PLATFORM, (cl_context_properties)(platforms[0])(), 0}; 
     cl::Context context(CL_DEVICE_TYPE_CPU, properties); 

     std::vector<cl::Device> devices = context.getInfo<CL_CONTEXT_DEVICES>(); 

     cl::Program::Sources source(1, 
      std::make_pair(helloStr,strlen(helloStr))); 
     cl::Program program_ = cl::Program(context, source); 
     program_.build(devices); 

     cl::Kernel kernel(program_, "hello", &err); 

     cl::Event event; 
     cl::CommandQueue queue(context, devices[0], 0, &err); 
     queue.enqueueNDRangeKernel(
      kernel, 
      cl::NullRange, 
      cl::NDRange(4,4), 
      cl::NullRange, 
      NULL, 
      &event); 

     event.wait(); 
    } 
    catch (cl::Error err) { 
     std::cerr 
      << "ERROR: " 
      << err.what() 
      << "(" 
      << err.err() 
      << ")" 
      << std::endl; 
    } 

    return EXIT_SUCCESS; 
} 

io uso lo stesso file del kernel da quel post sul blog, in ogni modo che non è il problema dato che non riesco a superare la compilazione.

Sto compilando il programma con il seguente comando:

g++ example.cpp -o example -l OpenCL 

e ottengo il seguente messaggio di errore: roba

/tmp/ccbUf7dB.o: In function `cl::detail::ReferenceHandler<_cl_device_id*>::release(_cl_device_id*)': 
example.cpp:(.text._ZN2cl6detail16ReferenceHandlerIP13_cl_device_idE7releaseES3_[_ZN2cl6detail16ReferenceHandlerIP13_cl_device_idE7releaseES3_]+0x14): undefined reference to `clReleaseDevice' 
collect2: error: ld returned 1 exit status 

ho letto su clReleaseDevice non funziona per dispositivi legacy (vedere ad esempio this question), ma la mia scheda grafica è piuttosto recente (NVidia GTX 660 Ti, supporta OpenCL 1.2). Dove posso andare da lì?

L'ho eseguito su Ubuntu 13.04 x64 con nvidia-opencl-dev e opencl-headers installati dai repository di ubuntu.

+0

Prova ad aggiungere '-DCL_USE_DEPRECATED_OPENCL_1_1_APIS' al tuo makefile. – Thomas

+0

Non cambia nulla. Ho sfogliato il file CL/cl.hpp e il codice in bundle con questa definizione non sembra essere correlato a questa chiamata di funzione. – levesque

+0

Cosa succede se metti '#define CL_USE_DEPRECATED_OPENCL_1_1_APIS; #include "CL/cl.h"; #undef CL_VERSION_1_2; #define __CL_ENABLE_EXCEPTIONS; #include "cl-1.2.hpp" 'Funziona? L'ho provato su Amazon AWS nvidia, con ubuntu 14.04, e sembra funzionare bene? –

risposta

10

La radice causa

Il problema è che la biblioteca OpenCL che si collega contro non supporta OpenCL 1.2. Parlando in termini generici, fino a quando un'implementazione OpenCL che supporta la versione che si desidera utilizzare diventa disponibile per una piattaforma specifica, si avrà questo problema quando si collega alla libreria condivisa OpenCL fornita con essa. Ci sono due soluzioni:

  • scaricare la versione di cl.hpp da Khronos che corrisponde alla versione OpenCL fornito dal vostro hardware scelto e continuare a utilizzare la libreria fornita dal produttore del dispositivo.
  • Collegamento a una libreria condivisa OpenCL che implementa l'ultimo standard OpenCL, ma scrive più percorsi di codice, uno per ogni versione di OpenCL, assicurando che ogni percorso di codice utilizzi solo le funzioni OpenCL supportate da tale versione. Questo percorso è più difficile e non ho idea di come sia possibile farlo con il wrapper C++. Se si tenta di chiamare una funzione di OpenCL 1.2 su una piattaforma che non supporta OpenCL 1.2, si otterrà un segfault, ecco perché sono necessari percorsi di codice diversi.

Nvidia specifico

Nvidia è stata molto lenta nel fornire OpenCL 1.2 il supporto. Di conseguenza, la loro libreria OpenCL non forniva le funzioni di OpenCL 1.2 che il linker cercava, risultando negli errori.

Alla fine di maggio 2015 Nvidia ha rilasciato driver che supportano OpenCL 1.2, vedere i commenti di Z Boson di seguito. L'aggiornamento dei driver dovrebbe risolvere l'errore del linker. Le schede GeForce GTX 6xx e successive (ad eccezione dei rebrands delle generazioni precedenti) supportano OpenCL 1.2. Puoi controllare lo conformant products list sul sito di Khronos OpenCL per essere sicuro. La GTX 660 Ti è elencata quindi sei fortunato.

+0

Ho ottenuto il supporto per OpenCL 1.2 da un po 'di googling, ma sembra che mi sia sbagliato! Grazie. – levesque

+0

Grazie per questo - ho appena incontrato lo stesso problema! –

+2

Nvidia ora supporta OpenCL 1.2 su Linux e Windows http://www.phoronix.com/scan.php?page=article&item=amdnv-phoronix-11&num=5 "Recentemente, NVIDIA ha finalmente aggiunto il supporto di OpenCL 1.2 al proprio driver Linux proprietario ". e https://devtalk.nvidia.com/default/topic/540773/opencl-1-2-support-in-nvidia-drivers/ "Sì, i driver Win10 più recenti di NVIDIA 352.84 e 352.63 includono il supporto per OpenCL 1.2." –

0

Sì. Non ho mai visto OpenCL 1.2 su dispositivi Nvidia. Compilare questo sul vostro sistema, e guardare il "OpenCL C Version":

#include <iostream> 
#include <vector> 
#include <CL/cl.hpp> 

int main() { 

    // Get the platforms 
    std::vector<cl::Platform> platforms; 
    cl::Platform::get(&platforms); 

    // Loop over the number of platforms 
    for (size_t i = 0; i < platforms.size(); ++i) { 

     // Display the platform information 
     std::cout << "Platform " << i+1 << ": " 
          << platforms[i].getInfo<CL_PLATFORM_NAME>() 
     << "\n----------------------------------------------" 
     << "\nVendor : " << platforms[i].getInfo<CL_PLATFORM_VENDOR>() 
     << "\nVersion : " << platforms[i].getInfo<CL_PLATFORM_VERSION>(); 

     // Get the devices on the current platform 
     std::vector <cl::Device> devices; 
     platforms[i].getDevices(CL_DEVICE_TYPE_ALL , & devices); 

     // Loop over the devices 
     std::cout << "\n----------------------------------------------\n"; 
     for (size_t j = 0; j < devices.size(); ++j) { 

      // Display the device information 
      std::cout 
      << "\n Device " << j+1 << ": " 
      <<   devices[j].getInfo<CL_DEVICE_NAME>() 
      << "\n\t Device Version  : " 
      <<   devices[j].getInfo<CL_DEVICE_VERSION>() 
      << "\n\t OpenCL C Version : " 
      <<   devices[j].getInfo<CL_DEVICE_OPENCL_C_VERSION>() 
      << "\n\t Compute Units  : " 
      <<   devices[j].getInfo<CL_DEVICE_MAX_COMPUTE_UNITS>() 
      << "\n\t Max Work Group Size: " 
      <<   devices[j].getInfo<CL_DEVICE_MAX_WORK_GROUP_SIZE>() 
      << "\n\t Clock Frequency : " 
      <<   devices[j].getInfo<CL_DEVICE_MAX_CLOCK_FREQUENCY>() 
      << "\n\t Local Memory Size : " 
      <<   devices[j].getInfo<CL_DEVICE_LOCAL_MEM_SIZE>() 
      << "\n\t Global Memory Size : " 
      <<   devices[j].getInfo<CL_DEVICE_GLOBAL_MEM_SIZE>(); 

      // Check if the device supports double precision 
      std::string str = devices[j].getInfo<CL_DEVICE_EXTENSIONS>(); 
      size_t found = str.find("cl_khr_fp64"); 
      std::cout << "\n\t Double Precision : "; 
      if (found != std::string::npos){ std::cout << "yes\n"; } 
      else {        std::cout << "no\n"; } 
     } 
     std::cout << "\n----------------------------------------------\n"; 
    } 
// std::cin.ignore(); 
    return 0; 
} 
Problemi correlati