2014-12-08 4 views
0

Я пытаюсь понять простой пример OpenCL, который является добавлением вектора. Ядро:Open global_work_size недоразумение

__kernel void addVec(__global double* a, __global double* b, __global double* c) 
{ 
    size_t id = get_global_id(0); 
    c[id] = a[id] + b[id]; 
} 

Например, мои входные массивы имеют размер 1 миллион элементов каждый.

В моей программе-хоста я установил global_work_size как размер векторов входных массивов (1 миллион).

Но когда я устанавливаю его на меньшее значение, например 1000, он также работает с этим ядром!

Я не понимаю, почему global_work_size может быть меньше размерности задачи, и все же программа OpenCL вычисляет все элементы входных массивов.

Не могли бы прояснить это?

EDIT: Вот код, где я копирую данные:

size_t arraySize = 1000000; 
const size_t global_work_size[1] = {512}; 

double *host_a = malloc(arraySize*sizeof(double)); 
double *host_b = malloc(arraySize*sizeof(double)); 
double *host_c = calloc(arraySize, sizeof(double)); 

... 

// Create the input and output arrays in device memory for our calculation 
device_a = clCreateBuffer(context, CL_MEM_READ_ONLY, arraySize*sizeof(double), NULL, NULL); 
device_b = clCreateBuffer(context, CL_MEM_READ_ONLY, arraySize*sizeof(double), NULL, NULL); 
device_c = clCreateBuffer(context, CL_MEM_WRITE_ONLY, arraySize*sizeof(double), NULL, NULL); 

... 

// Copy data set into the input array in device memory. [host --> device] 
status = clEnqueueWriteBuffer(command_queue, device_a, CL_TRUE, 0, arraySize*sizeof(double), host_a, 0, NULL, NULL); 
status |= clEnqueueWriteBuffer(command_queue, device_b, CL_TRUE, 0, arraySize*sizeof(double), host_b, 0, NULL, NULL); 

... 

// Copy-back the results from the device [host <-- device] 
clEnqueueReadBuffer(command_queue, device_c, CL_TRUE, 0, arraySize*sizeof(double), host_c, 0, NULL, NULL); 

... 
printf("checking result validity ...\n"); 
for (size_t i=0; i<arraySize; ++i) 
    if(host_c[i] - 1 > 1e-6) // the array is supposed to be 1 everywhere 
    { 
    printf("*** ERROR! Invalid results ! host_c[%zi]=%.9lf\n", i, host_c[i]); 
    break; 
    } 

Благодарности

+1

Предоставление global_work_Size = 1000 для 1 миллиона элементов и чтение результатов из 1 миллиона элементов, которые вы получаете правильные результаты. Если это так, вы должны очистить свой буфер C, т. Е. Установить c [0 - (Миллион -1)] = 0, направить данные на gpu и затем прочитать. (это происходит потому, что в разных прогонах память сопоставляется с тем же адресом, где результаты были вычислены во время предыдущих прогонов, и когда вы читаете назад, вы получаете результаты предыдущего запуска) – Meluha

+0

@Meluha Спасибо, на самом деле мой хост-буфер уже инициализирован с помощью ' calloc'. Кажется, что каждая вещь тоже очищается. – carmellose

+0

, чтобы убедиться, что вы копируете буфер c в GPU. – Meluha

ответ

1

Ваш тест функция не выглядит хорошо, она будет выполняться для любого value < 1, это должно быть так :

for (size_t i=0; i<arraySize; ++i){ 
    cl_double val = host_c[i] - 1; // the array is supposed to be 1 everywhere 
    if((val > 1e-6) || (val < -1e-6)) 
    { 
    printf("*** ERROR! Invalid results ! host_c[%zi]=%.9lf\n", i, host_c[i]); 
    break; 
    } 
} 

Non размеченное значение в ГПУ, скорее всего, будет 0, поэтому встреч вашего состояния.

Кроме того, помните, что если вы запустите программу один раз с полным размером, последовательные чтения по-прежнему будут содержать надлежащие обработанные данные (даже если вы закроете и снова откроете приложение). Поскольку память GPU не очищается после создания/уничтожения буфера.

Смежные вопросы