2014-09-17 32 views
5

Pracuję w jakimś kodzie, który wysyła duże ilości danych z hosta do urządzenia, i zachowuje się nieregularnie.Uszkodzenie pamięci za pomocą clEnqueueWriteBuffer - OpenCL

W poniższym kodzie próbuję wysłać z hosta do urządzenia tablicę. Rozmiar macierzy zwiększa się w każdej iteracji, stopniowo zwiększając ilość pamięci wysyłanej do urządzenia. Pierwszy element w tablicy jest wypełniany niezerową wartością i jest odczytywany z wnętrza jądra i drukowany na konsoli. Wartość powinna być taka sama, gdy jest odczytywana z hosta i urządzenia, ale w niektórych iteracjach tak nie jest.

Oto kod:


    int SizeArray = 0; 

    for(int j=1; j<100 ;j++){ 

     //Array memory allocation, starting with 4MB in first iteration to 400MB in last one 
     SizeArray = j * 1000000 * sizeof(float); 
     Array = (float*)malloc(SizeArray); 
     memset(Array, 0, SizeArray); 

     //Give the array's first element some nonzero value 
     //This is the value that is expected to be printed by the kernel execution 
     Array[0] = j; 

     memArray = clCreateBuffer(context, CL_MEM_READ_WRITE, SizeArray, NULL, &ret); 

     //Write the array contents into the buffer inside the device 
     ret = clEnqueueWriteBuffer(command_queue, memArray, CL_TRUE, 0, SizeArray, Array, 0, NULL, NULL); 
     ret = clSetKernelArg(kernel, 0, sizeof(cl_mem), (void *)&memArray); 

     getchar(); 

     //Execute the kernel where the content of the first element of the array will be printed 
     ret = clEnqueueNDRangeKernel(command_queue, kernel, 3, NULL, mGlobalWorkSizePtr, mLocalWorkSizePtr, 0, NULL,NULL); 
     ret = clFinish(command_queue); 

     /****** FAIL! Kernel prints correct value of Array's first element ONLY IN 
     SOME ITERATIONS (when it fails zero values are printed)! Depending on SizeArray :?? ******/ 

     free(Array); 
     ret = clReleaseMemObject(memArray); 
    } 

Urządzenie gdzie ten kod został przetestowany posiada następujące cechy:

 

         
 
    - Name: Intel(R) HD Graphics 4000 - DeviceVersion: OpenCL 1.1 - DriverVersion: 8.15.10.2696 - MaxMemoryAllocationSize: 425721856 - GlobalMemoryCacheSize: 2097152 - GlobalMemorySize: 1702887424 - MaxConstantBufferSize: 65536 - LocalMemorySize: 65536

jądra drukuje niepoprawne wartości lub nie, w zależności od wielkości bufora wysyłanych do urządzenia .

Oto wynik:


Array GPU: 1.000000 
Array GPU: 2.000000 
Array GPU: 3.000000 
Array GPU: 4.000000 
Array GPU: 5.000000 
Array GPU: 6.000000 
Array GPU: 7.000000 
Array GPU: 8.000000 
Array GPU: 9.000000 
Array GPU: 10.000000 
Array GPU: 11.000000 
Array GPU: 12.000000 
Array GPU: 13.000000 
Array GPU: 14.000000 
Array GPU: 15.000000 
Array GPU: 16.000000 
Array GPU: 17.000000 
Array GPU: 18.000000 
Array GPU: 19.000000 
Array GPU: 20.000000 
Array GPU: 21.000000 
Array GPU: 22.000000 
Array GPU: 23.000000 
Array GPU: 24.000000 
Array GPU: 25.000000 
Array GPU: 0.000000  <-------- INCORRECT VALUE, kernel is receiving corrupted memory 
Array GPU: 0.000000  <-------- INCORRECT VALUE, kernel is receiving corrupted memory 
Array GPU: 0.000000  <-------- INCORRECT VALUE, kernel is receiving corrupted memory 
Array GPU: 0.000000  <-------- INCORRECT VALUE, kernel is receiving corrupted memory 
Array GPU: 0.000000  <-------- INCORRECT VALUE, kernel is receiving corrupted memory 
Array GPU: 0.000000  <-------- INCORRECT VALUE, kernel is receiving corrupted memory 
Array GPU: 0.000000  <-------- INCORRECT VALUE, kernel is receiving corrupted memory 
Array GPU: 0.000000  <-------- INCORRECT VALUE, kernel is receiving corrupted memory 
Array GPU: 34.000000 
Array GPU: 35.000000 
Array GPU: 36.000000 
Array GPU: 37.000000 
Array GPU: 38.000000 
Array GPU: 39.000000 
Array GPU: 40.000000 
Array GPU: 41.000000 
Array GPU: 42.000000 
Array GPU: 43.000000 
Array GPU: 44.000000 
Array GPU: 45.000000 
Array GPU: 46.000000 
Array GPU: 47.000000 
Array GPU: 48.000000 
Array GPU: 49.000000 
Array GPU: 50.000000 
Array GPU: 51.000000 
Array GPU: 52.000000 
Array GPU: 53.000000 
Array GPU: 54.000000 
Array GPU: 55.000000 
Array GPU: 56.000000 
Array GPU: 57.000000 
Array GPU: 58.000000 
Array GPU: 0.000000  <-------- INCORRECT VALUE, kernel is receiving corrupted memory 
Array GPU: 0.000000  <-------- INCORRECT VALUE, kernel is receiving corrupted memory 
Array GPU: 0.000000  <-------- INCORRECT VALUE, kernel is receiving corrupted memory 
Array GPU: 0.000000  <-------- INCORRECT VALUE, kernel is receiving corrupted memory 
Array GPU: 0.000000  <-------- INCORRECT VALUE, kernel is receiving corrupted memory 
Array GPU: 0.000000  <-------- INCORRECT VALUE, kernel is receiving corrupted memory 
Array GPU: 0.000000  <-------- INCORRECT VALUE, kernel is receiving corrupted memory 
Array GPU: 0.000000  <-------- INCORRECT VALUE, kernel is receiving corrupted memory 
Array GPU: 0.000000  <-------- INCORRECT VALUE, kernel is receiving corrupted memory 
Array GPU: 68.000000 
Array GPU: 69.000000 
... 

Jak widać, nieprawidłowe wartości są odbierane przez urządzenie bez widocznego wzoru, a nie kod błędu zwrócony przez clEnqueueWriteBuffer funkcji.

Podsumowując: Blok pamięci jest wysyłany do jądra, ale jądro otrzymuje pamięć zerową w zależności od wysłanego całkowitego rozmiaru bloku.

Ten sam kod testowany na różnych komputerach zachowuje się inaczej (nieprawidłowe wartości w różnych iteracjach).

Jak można uniknąć uszkodzenia pamięci? Czy czegoś brakuje?

Z góry dziękuję.


Here jest kompletny kod roboczych:


Edit: Po kilku testach, należy wyjaśnić, że problem nie leży w printf. Problem wydaje się być związany z transferem danych do urządzenia, przed uruchomieniem jądra.

Here to kod bez wykonywania jądra. Wyniki są nadal błędne.

+1

Wszystko to wygląda jak kod C, możesz odcyfrować C++, chyba że chcesz otrzymywać liczne komentarze i odpowiedzi "nie używaj malloc, new, use vector". – Borgleader

+1

Czy sprawdzasz zwracane wartości różnych wywołań interfejsu API OpenCL? Otrzymujesz wartości zwracane (ret = ...), ale ignorujesz zwróconą wartość. Przydałoby się wiedzieć, czy jedna z tych funkcji nie działa. – dsharlet

+0

Wartości zwracane każdej funkcji openCL są drukowane w pełnym kodzie roboczym, który jest połączony na końcu postu. Usunąłem te linie z fragmentu kodu wewnątrz postu tylko po to, aby go uprościć. Jednak sprawdziłem wartości zwracane każdej funkcji oraz w przypadkach, gdy jądro zwraca zero (zła wartość), żadne z nich nie zwraca kodu błędu. Dziękuję za odpowiedź. – Backgroung

Odpowiedz

0

Czy próbowałeś

CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR 

ponieważ twoje akcje samej pamięci GPU z CPU?

Urządzenie znajduje się w tym samym miejscu hosta dla twojego iGPU.

Utwórz bufory, wykonaj testy obciążeniowe, jeśli wszystkie z nich uzyskają nieprawidłowe wartości, a następnie zainstaluj inną wersję sterownika prawdopodobnie nowszą, jeśli to nie rozwiąże problemu, RMA twoja karta.

Jeśli tylko jeden bufor jest błędny, to jest to prosty błąd vram, oznacz, że bufor jest bezużyteczny i utwórz nowe bufory, co jest konieczne i unikaj tego bufora, ale nie jestem pewien, czy sterownik wymienia bufory w tle. Jeśli każde jądro działa nieprawidłowo, rdzenie również mogą zostać uszkodzone.

+0

Po prostu próbuję utworzyć bufor dodając flagę _CL_MEM_ALLOC_HOST_PTR_, ale wyniki są takie same. Ponadto uruchamiam kod na dwóch komputerach z tym samym sprzętem i sterownikami, niż ten, który napisałem na pierwszym miejscu, i zwracają również błędne wyniki. Komputer to _Dell Vostro_ z zastrzeżonymi sterownikami, a najnowsza aktualizacja miała miejsce w 2012 roku. Gdy zainstalowałem tę najnowszą aktualizację, komputer zaczyna rozpoznawać procesor oprócz GPU i uruchamia kod OpenCL w CPU, wyniki są poprawne. GPU nadal zwraca błędne i błędne wyniki. Dziękuję za odpowiedź. – Backgroung