2015-12-14 3 views
0

Я пытаюсь проверить новые функции 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 на устройстве, чтобы быть в порядке. Однако, по крайней мере, для правильной печати массива.

Любые идеи, как мне получить такой странный выход?

+1

Почему вы передаете ядру указатель на пустоту, а затем вы его бросаете? Кроме того, вы должны быть уверены, что int и int соответствуют хосту и устройству. Потому что int может быть 16/32/64 в зависимости от системы. Хотя cl_int (то, что вы должны были использовать) всегда 32 бит. – DarkZeros

+1

Проверьте, правильно ли вы получаете результат при использовании OpenCL 1.x.Также убедитесь, что вы используете новейшие драйверы - у меня возникла аналогичная странная проблема, которая позже была исправлена ​​с обновлением драйверов. – doqtor

+1

Вообще говоря, использование printf для проверки чего-то является рискованным, поскольку оно полностью отлаживается и экспериментально (оно также нарушает модель исполнения OpenCL [полностью параллельная синхронизация]). Проверка вывода - лучшая идея. Например, возможно, компилятор оптимизировал все ядро, так как вы нигде не записываете входные данные. – DarkZeros

ответ

1

Вообще говоря, использование printf для проверки чего-либо является рискованным, поскольку оно полностью отлаживается и экспериментально (оно также нарушает модель исполнения OpenCL [полностью параллельна синхронизации]). Проверка вывода - лучшая идея. Например, возможно, компилятор оптимизировал все ядро, так как вы нигде не записываете входные данные. - DarkZeros

Оказывается, printf не является надежным, и когда я изменил входной массив и отобразил его обратно на хост, содержимое было совершенно правильным. - Kareem Ergawy

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