Я пытаюсь проверить новые функции SVM OpenCl 2.0. Я использую AMD-APP-SDK на машине, которая имеет следующие возможности SVM:OpenCl shared virtual memory test странные результаты
- CL_DEVICE_SVM_COARSE_GRAIN_BUFFER: 1 (поддерживается)
- CL_DEVICE_SVM_FINE_GRAIN_BUFFER: 1 (поддерживается)
- CL_DEVICE_SVM_FINE_GRAIN_SYSTEM: 0 (не поддерживается)
- CL_DEVICE_SVM_ATOMICS: 0 (не поддерживается)
Я тестирование с очень простым примером, в котором я делаю следующее (после настройки объектов OpenCL конечно):
На принимающей стороне:
- Выделяют буфер SVM.
- Карта, заполнить и отменить этот буфер.
- Настройка ядра.
- Передайте буфер SVM в качестве аргумента.
- Вызвать ядро.
Вот соответствующий код хоста:
int status;
cl_int cl_status;
int num_elements = 10;
status = SetupKernel("test_svm_kernel.cl", "test_svm_kernel");
CHECK_ERROR(status, "SetupKernel");
svm_input = clSVMAlloc(context, CL_MEM_READ_WRITE, num_elements*sizeof(int),
0);
CHECK_ALLOCATION(svm_input, "svm_input");
cl_status = clEnqueueSVMMap(queue, CL_TRUE,
CL_MAP_WRITE_INVALIDATE_REGION,
svm_input, num_elements*sizeof(int), 0, NULL,
NULL);
CHECK_OPENCL_ERROR(cl_status, "clEnqueueSVMMap");
for(int i=0 ; i<num_elements ; i++)
{
((int*)svm_input)[i] = i;
}
for(int i=0 ; i<num_elements ; i++)
{
std::cout << i << ", " << ((int*)svm_input)[i] << std::endl;
}
cl_status = clEnqueueSVMUnmap(queue, svm_input, 0, NULL, NULL);
CHECK_OPENCL_ERROR(cl_status, "clEnqueueSVMUnmap");
cl_status = clGetKernelWorkGroupInfo(
kernel, device, CL_KERNEL_WORK_GROUP_SIZE, sizeof(size_t),
&kernel_wrkgrp_size, NULL);
CHECK_OPENCL_ERROR(cl_status, "clGetKernelWorkGroupInfo");
cl_status = clGetKernelWorkGroupInfo(
kernel, device, CL_KERNEL_LOCAL_MEM_SIZE, sizeof(cl_ulong),
&compile_wrkgrp_size, NULL);
CHECK_OPENCL_ERROR(cl_status, "clGetKernelWorkGroupInfo");
cl_status = clGetKernelWorkGroupInfo(
kernel, device, CL_KERNEL_COMPILE_WORK_GROUP_SIZE,
sizeof(size_t)*3, &compile_wrkgrp_size, NULL);
CHECK_OPENCL_ERROR(cl_status, "clGetKernelWorkGroupInfo");
size_t local_threads = 1;//kernel_wrkgrp_size;
size_t globl_threads = num_elements;
cl_status = clSetKernelArgSVMPointer(kernel, 0, (void*)(svm_input));
CHECK_OPENCL_ERROR(cl_status, "clSetKernelArgSVMPointer");
cl_event ndr_event;
cl_status = clEnqueueNDRangeKernel(queue, kernel, 1, NULL,
&globl_threads, NULL,
0, NULL, &ndr_event);
CHECK_OPENCL_ERROR(cl_status, "clEnqueueNDRangeKernel");
cl_status = clFlush(queue);
CHECK_OPENCL_ERROR(cl_status, "clFlush");
На стороне ядра: ядро действительно просто.
__kernel void test_svm_kernel(__global void* input)
{
__global int* intInput = (__global int*)(input);
int idx = get_global_id(0);
printf("intInput[%d] = %d\n", idx, intInput[idx]);
}
Вывод, который я получаю в ополчении:
Host: input[0] = 0
Host: input[1] = 1
Host: input[2] = 2
Host: input[3] = 3
Host: input[4] = 4
Host: input[5] = 5
Host: input[6] = 6
Host: input[7] = 7
Host: input[8] = 8
Host: input[9] = 9
что естественный ожидаемый выход.
На ядре, я получаю странный вывод (и это меняет иногда):
input[0] = 0
input[1] = 2
input[3] = 1
input[5] = 5
input[1] = 7
input[8] = 1
input[0] = 0
input[0] = 0
input[0] = 0
input[0] = 0
Я не ожидаю PRINTF на устройстве, чтобы быть в порядке. Однако, по крайней мере, для правильной печати массива.
Любые идеи, как мне получить такой странный выход?
Почему вы передаете ядру указатель на пустоту, а затем вы его бросаете? Кроме того, вы должны быть уверены, что int и int соответствуют хосту и устройству. Потому что int может быть 16/32/64 в зависимости от системы. Хотя cl_int (то, что вы должны были использовать) всегда 32 бит. – DarkZeros
Проверьте, правильно ли вы получаете результат при использовании OpenCL 1.x.Также убедитесь, что вы используете новейшие драйверы - у меня возникла аналогичная странная проблема, которая позже была исправлена с обновлением драйверов. – doqtor
Вообще говоря, использование printf для проверки чего-то является рискованным, поскольку оно полностью отлаживается и экспериментально (оно также нарушает модель исполнения OpenCL [полностью параллельная синхронизация]). Проверка вывода - лучшая идея. Например, возможно, компилятор оптимизировал все ядро, так как вы нигде не записываете входные данные. – DarkZeros