Sto lavorando su un codice che invia grandi quantità di dati da host a dispositivo e si comporta in modo irregolare.Corruzione della memoria con clEnqueueWriteBuffer - OpenCL
Nella seguente parte del codice, sto provando a inviare da un dispositivo host a un array. La dimensione dell'array si incrementa a ogni iterazione, aumentando gradualmente la quantità di memoria inviata al dispositivo. Il primo elemento dell'array viene riempito con un valore diverso da zero e viene letto dall'interno del kernel e stampato sulla console. Il valore dovrebbe essere lo stesso quando viene letto dall'host e dal dispositivo, ma in alcune iterazioni non lo è.
Ecco il codice:
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);
}
Il dispositivo in cui questo codice è stato testato ha le seguenti caratteristiche:
-
- 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 stampe valori errati o no, a seconda delle dimensioni del buffer inviati al dispositivo .
ecco l'output:
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
...
Come si può vedere, i valori non corretti vengono ricevuti dal dispositivo senza alcun motivo apparente, e nessun codice di errore viene restituito da clEnqueueWriteBuffer funzione.
Per riepilogare: Un blocco di memoria viene inviato al kernel, ma il kernel riceve memoria azzerata a seconda della dimensione del blocco totale inviata.
Lo stesso codice testato su computer diversi si comporta in modo diverso (valori errati in iterazioni diverse).
Come può essere evitata la corruzione della memoria? Mi sto perdendo qualcosa?
Grazie in anticipo.
Here s' il codice di lavoro completo:
Edit: Dopo alcuni test, ha bisogno di essere chiarire che il problema non è nel printf. Il problema sembra essere nel trasferimento dei dati al dispositivo, precedente all'esecuzione del kernel.
Here 's il codice senza l'esecuzione del kernel. I risultati sono ancora sbagliati.
Tutto questo sembra codice C, è possibile che si desideri rimuovere il tag C++ a meno che non si desideri ricevere numerosi commenti/risposte "non usare malloc o nuovo vettore uso". – Borgleader
Stai verificando i valori di ritorno delle varie chiamate API OpenCL? Stai ottenendo i valori di ritorno (ret = ...) ma poi ignorando il valore restituito. Sarebbe utile sapere se una di quelle funzioni sta fallendo. – dsharlet
I valori di ritorno di ogni funzione openCL sono stampati nel codice di lavoro completo che è collegato alla fine del post. Ho rimosso quelle righe nel pezzo di codice all'interno del post solo per semplificarlo. Tuttavia, ho controllato i valori di ritorno di ogni funzione e nei casi in cui il kernel restituisce zero (valore errato) nessuno di essi restituisce un codice di errore. Grazie per la risposta. – Backgroung