2014-09-17 1 views
5

Я работаю в некотором коде, который отправляет большие объемы данных с хоста на устройство и ведет себя беспорядочно.Повреждение памяти с помощью clEnqueueWriteBuffer - OpenCL

В следующем фрагменте кода я пытаюсь отправить с узла на устройство массив. Размер массива увеличивается на каждой итерации, постепенно увеличивая объем памяти, отправляемой на устройство. Первый элемент массива заполняется ненулевым значением, и он считывается изнутри ядра и печатается на консоль. Значение должно быть таким же, когда оно считывается с хоста и с устройства, но в некоторых итерациях это не так.

Вот код:


    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); 
    } 

Устройство, где этот код был проверен, имеет следующие особенности:

 

         
 
    - 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

Kernel печатает неправильные значения или нет, в зависимости от размера буфера, отправляемые на устройство ,

Вот результат:


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 
... 

Как вы можете видеть, неправильные значения, полученные с помощью устройства без явного рисунка, и код ошибки не возвращается clEnqueueWriteBuffer функции.

Подводя итог: блок памяти отправляется в ядро, но ядро ​​получает нулевую память в зависимости от общего отправленного размера блока.

Тот же код, протестированный на разных компьютерах, ведет себя по-разному (неправильные значения в разных итерациях).

Как можно предотвратить повреждение памяти? Я что-то упускаю?

Заранее спасибо.


Here «s полный рабочий код:


Edit: После некоторых тестов, он должен быть уточнить, что проблема не в PRINTF. Кажется, что проблема заключается в передаче данных на устройство, предшествующих исполнению ядра.

Here код без выполнения ядра. Результаты все еще ошибочны.

+1

Все это похоже на C-код, вы можете захотеть разблокировать C++, если вы не хотите получать многочисленные комментарии «dont use malloc или new, use vector». – Borgleader

+1

Вы проверяете возвращаемые значения различных вызовов OpenCL API? Вы получаете возвращаемые значения (ret = ...), но затем игнорируете возвращаемое значение. Было бы полезно узнать, не работает ли одна из этих функций. – dsharlet

+0

Возвращаемые значения каждой функции openCL печатаются в полном рабочем коде, который связан в конце сообщения. Я удалил эти строки в куске кода внутри сообщения только для его упрощения. Тем не менее, я проверил возвращаемые значения каждой функции и в случаях, когда ядро ​​возвращает ноль (неправильное значение), ни один из них не возвращает код ошибки. Спасибо за ответ. – Backgroung

ответ

0

Вы пробовали

CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR 

поскольку ваш GPU разделяет то же память с процессором?

Устройство также находится на одном и том же месте хоста для вашего iGPU.

Создайте несколько буферов, сделайте стресс-тест на них, если все они получают недопустимые значения, а затем установите другую версию драйвера, возможно, более новую, если это не решит, RMA ваша карта.

Если только один буфер является ошибочным, то это простая ошибка vram, тег, который является буфером, как непригодный для использования, и создавать новые буферы как необходимые и избегать этого буфера, но я не уверен, что драйвер меняет буферы в фоновом режиме. Если каждое отдельное ядро ​​сработает, то могут быть повреждены и сердечники.

+0

Я просто пытаюсь создать буфер, добавляющий флаг _CL_MEM_ALLOC_HOST_PTR_, но результаты те же. Кроме того, я запускаю код на двух компьютерах с тем же оборудованием и драйверами, что и первый, и они возвращают также неправильные результаты. Компьютер является _Dell Vostro_ с проприетарными драйверами, а самое новое обновление - в 2012 году. Когда я установил это новейшее обновление, компьютер начинает распознавать CPU в дополнение к графическому процессору и запускает код OpenCL в CPU, результаты верны. GPU все еще возвращает неправильные и неустойчивые результаты. Спасибо за ответ. – Backgroung