Итак, я немного поиграл с OpenCL и проверил скорость передачи данных между хостом и устройством. Я использовал Intel OpenCL SDK и работал на Intel i5 Processor со встроенной графикой. Затем я обнаружил clEnqueueMapBuffer
вместо clEnqueueWriteBuffer
, который оказался быстрее почти в 10 раз при использовании возлагали памяти так:CL_MEM_ALLOC_HOST_PTR медленнее 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);
Где a
b
и ret
128 бит выровнен ИНТ массивы. время вышло около 22,026186 мс, по сравнению с 198,604528 мс с использованием clEnqueueWriteBuffer
Однако, когда я изменил мой код
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 **/
время увеличивается до 91,350065 мс
Что может быть проблемой? Или это проблема вообще?
EDIT: Это, как я инициализировать массивы во втором коде:
for (int i = 0; i < amt; i++)
{
map_a[i] = i;
map_b[i] = i;
}
И теперь, когда я проверяю, map_a и map_b сделать содержат правильные элементы в конце программы, но map_c содержит все 0. Я сделал это:
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);
и мое ядро просто
__kernel void test(__global int* a, __global int* b, __global int* c)
{
int i = get_global_id(0);
c[i] = a[i] + b[i];
}
во втором коде вы можете показать, как вы инициализируете k_a, k_b и k_c с данными a, b и ret и где clFinish. Если 2 кода делают разные вещи, вам будет сложно помочь –
Извините, код тот же, что я просто не копировал все случайно.Во втором коде я не инициализирую k_c с ret, потому что думал, что могу просто прочитать данные с map_c. – selena731
После сопоставления и использования вы должны либо отменить, либо выполнить clWrite/Read из сопоставленного объекта, чтобы обеспечить согласованность памяти. – DarkZeros