2014-09-17 12 views
5

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.

+1

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

+1

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

+0

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

risposta

0

Hai provato

CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR 

poiché vostre azioni GPU stessa memoria con la CPU?

Anche il dispositivo si trova nello stesso punto di hosting per l'iGPU.

Creare alcuni buffer, fare test di stress su di essi, se tutti ottengono valori non validi quindi installare un'altra versione del driver probabilmente una più nuova, se questo non risolve, RMA la tua carta.

Se solo un singolo buffer è errato, allora è semplice errore vram, tagga quel buffer come inutilizzabile e crea nuovi buffer come necessario ed evita quel buffer ma non sono sicuro se il driver scambia i buffer in background. Se ogni singolo kernel ha un malfunzionamento, anche i nuclei potrebbero essere danneggiati.

+0

Ho appena provato a creare il buffer aggiungendo il flag _CL_MEM_ALLOC_HOST_PTR_ ma i risultati sono gli stessi. Inoltre, eseguo il codice su due computer con lo stesso hardware e driver rispetto a quello che ho pubblicato in primo luogo e restituiscono anche risultati errati. Il computer è un _Dell Vostro_ con driver proprietari e l'aggiornamento più recente risale al 2012. Quando ho installato questo aggiornamento più recente, il computer inizia a riconoscere la CPU oltre alla GPU e, eseguendo il codice OpenCL nella CPU, i risultati sono corretti. GPU restituisce ancora risultati errati e irregolari. Grazie per la risposta. – Backgroung

Problemi correlati