Also habe ich jetzt ein bisschen mit OpenCL herumgespielt und die Geschwindigkeit des Speichertransfers zwischen Host und Gerät getestet. Ich verwendete Intel OpenCL SDK und lief auf dem Intel i5 Processor mit integrierter Grafik. entdeckte ich dann clEnqueueMapBuffer
statt clEnqueueWriteBuffer
die fast 10-mal schneller durch entpuppte, wenn wie so gepinnt Speicher mit:CL_MEM_ALLOC_HOST_PTR langsamer als 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);
Wo a
b
und ret
sind 128 Bit ausgerichtet int Arrays. Es kam die Zeit, um über 22,026186 ms, im Vergleich zu 198,604528 ms mit clEnqueueWriteBuffer
Allerdings, wenn ich meinen Code
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 **/
die Zeit erhöht sich auf 91,350065 ms
geändertWas könnte sei das Problem? Oder ist es überhaupt ein Problem?
EDIT: Dies ist, wie ich die Arrays in dem zweiten Code initialisiert werden:
for (int i = 0; i < amt; i++)
{
map_a[i] = i;
map_b[i] = i;
}
Und jetzt, wo ich überprüfen, map_a und map_b tun die richtigen Elemente am Ende des Programms enthalten, aber map_c enthält alle Nullen. Ich tat dies:
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);
und mein Kern ist nur
__kernel void test(__global int* a, __global int* b, __global int* c)
{
int i = get_global_id(0);
c[i] = a[i] + b[i];
}
im zweiten Code können Sie zeigen, wie initialisieren Sie k_a, k_b und k_c mit a, b und ret Daten und wo ist die ClFinish. Wenn die 2 Codes verschiedene Dinge tun, wäre es schwierig, Ihnen zu helfen. –
Entschuldigung, der Code ist der gleiche Ich habe einfach nicht alles versehentlich kopiert.Im zweiten Code initialisiere ich k_c nicht mit ret, weil ich dachte, ich könnte einfach die Daten von map_c lesen. – selena731
Nach dem Mapping und der Verwendung müssen Sie entweder die Zuordnung aufheben oder ein clWrite/Read vom zugeordneten Objekt ausführen, um die Konsistenz des Speichers zu gewährleisten. – DarkZeros