Quindi ho giocato un po 'con OpenCL per un po' e sto testando le velocità di trasferimento della memoria tra host e dispositivo. Stavo usando Intel OpenCL SDK e in esecuzione su Intel i5 Processor con grafica integrata. Ho poi scoperto clEnqueueMapBuffer
invece di clEnqueueWriteBuffer
che si è rivelato essere più veloce di quasi 10 volte quando si usa la memoria riposto in questo modo:CL_MEM_ALLOC_HOST_PTR più lento di CL_MEM_USE_HOST_PTR
int amt = 16*1024*1024;
...
k_a = clCreateBuffer(context,CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, sizeof(int)*amt, a, NULL);
k_b = clCreateBuffer(context,CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, sizeof(int)*amt, b, NULL);
k_c = clCreateBuffer(context,CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR, sizeof(int)*amt, ret, NULL);
int* map_a = (int*) clEnqueueMapBuffer(c_q, k_a, CL_TRUE, CL_MAP_READ, 0, sizeof(int)*amt, 0, NULL, NULL, &error);
int* map_b = (int*) clEnqueueMapBuffer(c_q, k_b, CL_TRUE, CL_MAP_READ, 0, sizeof(int)*amt, 0, NULL, NULL, &error);
int* map_c = (int*) clEnqueueMapBuffer(c_q, k_c, CL_TRUE, CL_MAP_WRITE, 0, sizeof(int)*amt, 0, NULL, NULL, &error);
clFinish(c_q);
Dove a
b
e ret
sono 128 array di int bit allineato. Il tempo è venuto fuori per circa 22,026,186 mila ms, rispetto al 198,604,528 mila ms utilizzando clEnqueueWriteBuffer
Tuttavia, quando ho cambiato il mio codice per
k_a = clCreateBuffer(context,CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR, sizeof(int)*amt, NULL, NULL);
k_b = clCreateBuffer(context,CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR, sizeof(int)*amt, NULL, NULL);
k_c = clCreateBuffer(context,CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR, sizeof(int)*amt, NULL, NULL);
int* map_a = (int*)clEnqueueMapBuffer(c_q, k_a, CL_TRUE, CL_MAP_READ, 0, sizeof(int)*amt, 0, NULL, NULL, &error);
int* map_b = (int*)clEnqueueMapBuffer(c_q, k_b, CL_TRUE, CL_MAP_READ, 0, sizeof(int)*amt, 0, NULL, NULL, &error);
int* map_c = (int*)clEnqueueMapBuffer(c_q, k_c, CL_TRUE, CL_MAP_WRITE, 0, sizeof(int)*amt, 0, NULL, NULL, &error);
/** initiate map_a and map_b **/
il tempo aumenta di 91,350,065 mila ms
Cosa potrebbe essere il problema? O è un problema?
EDIT: Ecco come ho inizializzare le matrici del secondo codice:
for (int i = 0; i < amt; i++)
{
map_a[i] = i;
map_b[i] = i;
}
E ora che posso controllare, map_a e map_b fare contengono gli elementi a destra alla fine del programma, ma map_c contiene tutti gli 0. Ho fatto questo:
clEnqueueUnmapMemObject(c_q, k_a, map_a, 0, NULL, NULL);
clEnqueueUnmapMemObject(c_q, k_b, map_b, 0, NULL, NULL);
clEnqueueUnmapMemObject(c_q, k_c, map_c, 0, NULL, NULL);
e il mio kernel è solo
__kernel void test(__global int* a, __global int* b, __global int* c)
{
int i = get_global_id(0);
c[i] = a[i] + b[i];
}
nel secondo codice è possibile mostrare come si inizializza k_a, k_b e k_c con a, b e rit i dati e dove si trova il clFinish. Se i 2 codici fanno cose diverse, sarebbe difficile aiutarti –
Spiacente, il codice è lo stesso, ma non ho copiato tutto casualmente.Nel secondo codice, non inizializzo k_c con ret perché pensavo che potessi semplicemente leggere i dati da map_c. – selena731
Dopo la mappatura e l'utilizzo, è necessario rimuovere la mappatura o eseguire un clWrite/Read dall'oggetto mappato per garantire la coerenza della memoria. – DarkZeros