2013-01-24 6 views
5

Napisałem jądro OpenCL w pliku .cl. Próbuje uzyskać kilka nagłówków.zawierają nagłówki do pliku OpenCL .cl

Jego kompilacja kończy się niepowodzeniem, ponieważ dołączone pliki nagłówkowe są "nieodnalezione". Mam świadomość, że clBuildProgram może pobrać opcję -I dir, która dodaje katalog dir do listy katalogów, które mają być wyszukiwane w poszukiwaniu plików nagłówkowych.

Na forum witryny khronus ten post http://www.khronos.org/message_boards/viewtopic.php?f=37&t=2535 mówi o problemie.

Proponują użyć clCreateProgramWithSource, która określa wszystkie źródła (w tym pliki .h).

mam pytania dotyczące tej kwestii:

  1. Która opcja jest lepsza? (clBuildProgram vs. clCreateProgramWithSource, jak opisano powyżej)
  2. Jeśli używam clCreateProgramWithSource, w jaki sposób kompilator wie, co należy uwzględnić? Chodzi mi o to, z którego źródła pochodzi nazwa pliku?
  3. Jeśli używam clBuildProgram i jest kilka katalogów z plikami włączającymi, jak je określić?

Odpowiedz

5

OpenCL wymaga korzystania clCreateProgramWithSource() następnie clBuildProgram().

ClCreateProgramWithSource() tworzy i zwraca obiekt cl_program.

Ten obiekt cl_program jest wprowadzany do clBuildProgram().

clBuildProgram() pozwala określić opcje kompilatora, które zawierają katalogi plików . W twoim przypadku, na plik zawiera nagłówek, to będzie coś w ciągu:

-I myincludedir1 -I myincludedir2 ... 

Kompilator stosowany jest kompilator wewnętrzny OpenCL w OpenCL SDK używasz. Jeśli więc używasz AMD, to zostanie użyty AMD OpenCL kompilator, który jest częścią ich OpenCL SDK. Podobnie dla Nvidia lub Intel.

Ważne jest sprawdzenie kodu statusu OpenCL dla WSZYSTKICH połączeń funkcji OpenCL. Jest to obowiązkowe dla clCreateProgramWithSource() i clBuildProrgam(), aby uzyskać wszelkie błędy lub komunikaty kompilatora. Istnieje cały inny kod bitowy do napisania w celu pobrania rozmiaru wiadomości, a następnie pobrania samych wiadomości.

2

Sterowniki urządzeń Nvidia OpenCL mają błąd podczas korzystania z opcji -I z pewną liczbą włączeń i długości kodu. AMD i Intel nie mają tego problemu. Moje rozwiązania polegają na połączeniu wszystkich plików .cl na jeden duży w czasie wykonywania.Wadą tego jest to, że podczas debugowania kodu numer wiersza błędu odpowiada skoordynowanemu plikowi .cl, a nie poszczególnym plikom .cl.

Wątpię, czy Nvidia kiedykolwiek to naprawi. Już nie interesują się OpenCL.

+0

AMD APP ma problemy z -I też z mojego doświadczenia (to po prostu nie działa), chociaż Intel obsługuje go doskonale. – Thomas

+0

To interesujące. Chociaż testowałem to na procesorze. Nie mam procesora graficznego AMD, więc nie mogę go przetestować na GPU. Może to problem z GPU vs. CPU? –

+0

Nie, próbowałem go pod obydwoma urządzeniami pod Windows, kompilator po prostu nie obsługuje względnych ścieżek dołączania. Zasadniczo, mam "-I cl /" w wierszu poleceń kompilatora, a moje jądra są uporządkowane w katalogu cl/i chociaż działa to dobrze w systemie Intel/Linux, AMD po prostu nie będzie miało żadnego z nich, bez względu na to, to, co próbuję, a jedynym rozwiązaniem, które znalazłem, było albo zakodowanie * absolutnej ścieżki * każdego pliku .cl w dyrektywach #include, albo dodanie mojego katalogu cl/do systemu $ PATH. Może to być moja instalacja, która jest zepsuta, nie utrzymuję systemu Windows tak bardzo, jak mój Linux. – Thomas

0

Jest jeszcze jedna brudna sztuczka: powinieneś naśladować sam siebie (np. Coś w rodzaju ręcznej fuzji). Kodowanie nie jest zbyt jasne, ale działa, jeśli twój kompilator OpenCL nie obsługuje (lub obsługuje niepoprawnie) dyrektyw -I. Takie podejście nie jest idealne (na przykład tracisz podświetlanie składni), ale może pomóc w przypadku starych lub błędnych kompilatorów OpenCL.

Mały Prostym przykładem takiej możliwości:

std::string load_file(const std::string &file_name, int max_size = 0x100000) 
{ 
    FILE *fp = fopen(file_name.c_str(), "rb"); 
    if (!fp) 
    { 
     // print some error or throw exception here 
     return std::string(); 
    } 
    char *source = new char[max_size]; 
    size_t source_size = fread(source, 1, max_size, fp); 
    fclose(fp); 
    if (!source_size) 
    { 
     delete[] source; 
     // print some error or throw exception here 
     return std::string(); 
    } 
    std::string result(source); 
    delete[] source; 
    return result; 
} 

// errors checks are omitted for simplification 
std::string full_source = load_file("header.h"); 
full_source += load_file("source.cl"); 

const char *source_ptr = full_source.c_str(); 
size_t source_size = full_source.size(); 
cl_int_status = CL_SUCCESS; 
cl_program program = clCreateProgramWithSource(context, 1, 
     (const char **)&source_ptr, (const size_t *)&source_size, &ret); 
// check status for CL_SUCCESS here 
// now you have your program (include + source)