Я работаю в некотором коде, который отправляет большие объемы данных с хоста на устройство и ведет себя беспорядочно.Повреждение памяти с помощью 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 код без выполнения ядра. Результаты все еще ошибочны.
Все это похоже на C-код, вы можете захотеть разблокировать C++, если вы не хотите получать многочисленные комментарии «dont use malloc или new, use vector». – Borgleader
Вы проверяете возвращаемые значения различных вызовов OpenCL API? Вы получаете возвращаемые значения (ret = ...), но затем игнорируете возвращаемое значение. Было бы полезно узнать, не работает ли одна из этих функций. – dsharlet
Возвращаемые значения каждой функции openCL печатаются в полном рабочем коде, который связан в конце сообщения. Я удалил эти строки в куске кода внутри сообщения только для его упрощения. Тем не менее, я проверил возвращаемые значения каждой функции и в случаях, когда ядро возвращает ноль (неправильное значение), ни один из них не возвращает код ошибки. Спасибо за ответ. – Backgroung