2017-09-23 19 views
1

私はOpenCL 1.1 EPをサポートするi.MX6qボードに実行するサンプルコードを開発しようとしています。CL_MEM_USE_HOST_PTRを使用してOpenCL 1.1で単純にコピー/ペーストの値を作成しようとしていますが、なぜ機能しませんか?

私は、the OpenCL 1.1 Reference pages、さらにthis OpenCL exampleの順で最初からOpenCLの実装/アプリケーションを作成しなければなりませんでした。

基本的には、ボード上で動作する「パフォーマンステスト」を開発することです。 2つのint配列(入力と出力)を持ち、最初のものをランダムな値で埋めて、OpenCLワークアイテムを使用して出力配列に貼り付けます。

clEnqueue(読み込み/書き込み)バッファ関数とclCreateBufferフラグ(特にCL_MEM_USE_HOST_PTR)の間でかなり混乱していましたので、一見して練習することにしました。

私のコードが正しくコンパイルと私は、出力配列の値を読んでいるときが正しく動作し、彼らはまだここで0

に泊まる(C++である)私のコードです:

void buffer_copy(char* kernelfile) 
{ 
    cl_platform_id  platform_id; 
    cl_device_id  device_id; 
    cl_context   context; 
    cl_command_queue cmd_queue; 
    cl_program   program; 

    // Retrieving all the OpenCL data needed 
    // to start the performance test 
    platform_id = get_platform(); 
    device_id = get_device(platform_id); 
    context = get_context(platform_id, device_id); 
    cmd_queue = get_command_queue(context, device_id); 
    program = get_program(context, kernelfile); 

    cl_mem  buffer_input, buffer_output; 
    size_t  buffer_width = 640, buffer_height = 480; 
    size_t  buffer_size = buffer_width * buffer_height; 
    cl_kernel kernel; 
    cl_int  err = 0; 
    char*  options = "-Werror -cl-std=CL1.1"; 

    int   data_input[buffer_size]; 
    int   data_output[buffer_size]; 

    // Assigning random values in the data_input array and 
    // initializing the data_output array to zero-values 
    srand(time(NULL)); 
    for (size_t index = 0; index < buffer_size; ++index) 
    { 
     data_input[index] = rand(); 
     data_output[index] = 0; 
    } 

    // Creating OpenCL buffers 
    buffer_input = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, buffer_size * sizeof(int), data_input, &err); 
    assert(err == CL_SUCCESS); 
    buffer_output = clCreateBuffer(context, CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR, buffer_size * sizeof(int), data_output, &err); 
    assert(err == CL_SUCCESS); 

    err = clBuildProgram(program, 1, &device_id, options, NULL, NULL); 
    assert(err == CL_SUCCESS); 
    kernel = clCreateKernel(program, "buffer_copy", &err); 
    assert(err == CL_SUCCESS); 

    clSetKernelArg(kernel, 0, sizeof(cl_mem), &buffer_input); 
    clSetKernelArg(kernel, 1, sizeof(cl_mem), &buffer_output); 

    size_t device_max_work_group_size; 
    size_t global_work_size, local_work_size; 
    size_t preferred_work_group_size_multiple; 

    cl_ulong global_mem_size, max_mem_alloc_size; 
    clGetDeviceInfo(device_id, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(cl_ulong), &global_mem_size, NULL); 
    clGetDeviceInfo(device_id, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof(cl_ulong), &max_mem_alloc_size, NULL); 
    clGetDeviceInfo(device_id, CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(size_t), &device_max_work_group_size, NULL); 
    std::cout << "Global device memory size: " << global_mem_size << " bytes" << std::endl; 
    std::cout << "Device max memory allocation size: " << max_mem_alloc_size << " bytes" << std::endl; 
    std::cout << "Device max work group size: " << device_max_work_group_size << std::endl; 

    clGetKernelWorkGroupInfo(kernel, device_id, CL_KERNEL_WORK_GROUP_SIZE, sizeof(size_t), &global_work_size, NULL); 
    std::cout << "global_work_size value: " << global_work_size << std::endl; 

    clGetKernelWorkGroupInfo(kernel, device_id, CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE, sizeof(size_t), &preferred_work_group_size_multiple, NULL); 
    local_work_size = global_work_size/preferred_work_group_size_multiple; 
    std::cout << "local_work_size value: " << local_work_size << std::endl; 

    cl_event events[2]; 
    err = clEnqueueNDRangeKernel(cmd_queue, kernel, 1, NULL, &global_work_size, &local_work_size, 0, 0, &events[0]); 
    assert (err == CL_SUCCESS); 
    err = clEnqueueReadBuffer(cmd_queue, buffer_output, CL_TRUE, 0, buffer_size * sizeof(int), data_output, 0, NULL, &events[1]); 
    assert (err == CL_SUCCESS); 
    err = clWaitForEvents(2, events); 
    assert (err == CL_SUCCESS); 

    for (size_t index = 0; index < buffer_size; ++index) 
    { 
     if (data_input[index] != data_output[index]) 
     { 
      std::cerr << "Error, values differ (at index " << index << ")." << std::endl; 
      break; 
     } 
     else 
     { 
      //std::cout << "data_input[index] =\t" << data_input[index] << std::endl; 
      //std::cout << "data_output[index] =\t" << data_output[index] << std::endl; 
     } 
    } 

    cl_ulong time_start, time_end; 
    double  total_time; 
    clGetEventProfilingInfo(events[0], CL_PROFILING_COMMAND_START, sizeof(time_start), &time_start, NULL); 
    clGetEventProfilingInfo(events[1], CL_PROFILING_COMMAND_END, sizeof(time_end), &time_end, NULL); 
    total_time = time_end - time_start; 
    std::cout << "Execution time in milliseconds: " << (total_time/1000000.0) << " ms" << std::endl; 

    clReleaseKernel(kernel); 
    clReleaseProgram(program); 
    clReleaseMemObject(buffer_input); 
    clReleaseMemObject(buffer_output); 
    clReleaseCommandQueue(cmd_queue); 
    clReleaseContext(context); 
} 

そして、ここに私のOpenCLカーネルがあります:

__kernel void buffer_copy(__global int* input, __global int* output) 
{ 
    int id = get_global_id(0); 

    output[id] = input[id]; 
} 

今私はそれを最適化しないようにしようとしています。そして、私はこことそこに良い点を見逃していると思うが、私はそれらをキャッチすることはできません。私の意見では、clCreateBufferフラグが混乱しています。

あなたは私を啓発し、この1つを手伝ってもらえますか?


EDIT:更新されたコード+新に関する情報!

値は正しく貼り付けられているようですが、カーネルのワークグループのサイズだけによると思われます.CL_DEVICE_MAX_WORK_GROUP_SIZEは1024を返し、CL_KERNEL_WORK_GROUP_SIZEも1024を返します(これも奇妙です)。だから私の配列の最初の1024の整数はよくコピーされ、貼り付けられますが、それ以降はそれ以上は動作しません。これを確認するために、私はglobal_work_group_sizeを手動で32に設定し、私のプログラムを再度実行して、最初の32個の整数だけを正しく貼り付けました。私は本当にここで何が起こっているのか分かりません。

答えて

0

ノートパソコンとi.MX6qボードの両方で動作させることができたと思います。ここで

が動作するコードです:あなたが見ることができるように

void buffer_copy(char* kernelfile) 
{ 
    cl_platform_id  platform_id; 
    cl_device_id  device_id; 
    cl_context   context; 
    cl_command_queue cmd_queue; 
    cl_program   program; 

    // Retrieving all the OpenCL data needed 
    // to start the performance test 
    platform_id = get_platform(); 
    device_id = get_device(platform_id); 
    context = get_context(platform_id, device_id); 
    cmd_queue = get_command_queue(context, device_id); 
    program = get_program(context, kernelfile); 

    cl_mem  buffer_input, buffer_output; 
    size_t  buffer_width = 640, buffer_height = 480; 
    size_t  buffer_size = buffer_width * buffer_height; 
    cl_kernel kernel; 
    cl_int  err = 0; 
    char*  options = "-Werror -cl-std=CL1.1"; 

    int   data_input[buffer_size]; 
    int   data_output[buffer_size]; 

    // Assigning random values in the data_input array and 
    // initializing the data_output array to zero-values 
    srand(time(NULL)); 
    for (size_t index = 0; index < buffer_size; ++index) 
    { 
     data_input[index] = rand(); 
     data_output[index] = 0; 
    } 

    // Creating OpenCL buffers 
    buffer_input = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, buffer_size * sizeof(int), data_input, &err); 
    assert(err == CL_SUCCESS); 
    buffer_output = clCreateBuffer(context, CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR, buffer_size * sizeof(int), data_output, &err); 
    assert(err == CL_SUCCESS); 

    err = clBuildProgram(program, 1, &device_id, options, NULL, NULL); 
    assert(err == CL_SUCCESS); 
    kernel = clCreateKernel(program, "buffer_copy", &err); 
    assert(err == CL_SUCCESS); 

    clSetKernelArg(kernel, 0, sizeof(cl_mem), &buffer_input); 
    clSetKernelArg(kernel, 1, sizeof(cl_mem), &buffer_output); 

    cl_ulong global_mem_size = 0, max_mem_alloc_size = 0; 
    size_t  device_max_work_group_size = 0; 
    size_t  kernel_work_group_size = 0; 
    size_t  preferred_work_group_size_multiple = 0; 
    clGetDeviceInfo(device_id, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(cl_ulong), &global_mem_size, NULL); 
    clGetDeviceInfo(device_id, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof(cl_ulong), &max_mem_alloc_size, NULL); 
    clGetDeviceInfo(device_id, CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(size_t), &device_max_work_group_size, NULL); 
    clGetKernelWorkGroupInfo(kernel, device_id, CL_KERNEL_WORK_GROUP_SIZE, sizeof(size_t), &kernel_work_group_size, NULL); 
    clGetKernelWorkGroupInfo(kernel, device_id, CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE, sizeof(size_t), &preferred_work_group_size_multiple, NULL); 
    std::cout << "CL_DEVICE_GLOBAL_MEM_SIZE : " << global_mem_size << " bytes" << std::endl; 
    std::cout << "CL_DEVICE_MAX_MEM_ALLOC_SIZE : " << max_mem_alloc_size << " bytes" << std::endl; 
    std::cout << "CL_DEVICE_MAX_WORK_GROUP_SIZE : " << device_max_work_group_size << std::endl; 
    std::cout << "CL_KERNEL_WORK_GROUP_SIZE : " << kernel_work_group_size << std::endl; 
    std::cout << "CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE : " << preferred_work_group_size_multiple << std::endl; 

    cl_event events[2]; 
    err = clEnqueueNDRangeKernel(cmd_queue, kernel, 1, NULL, &buffer_size, &kernel_work_group_size, 0, NULL, &events[0]); 
    assert (err == CL_SUCCESS); 
    err = clEnqueueReadBuffer(cmd_queue, buffer_output, CL_TRUE, 0, buffer_size * sizeof(int), data_output, 1, &events[0], &events[1]); 
    assert (err == CL_SUCCESS); 
    err = clWaitForEvents(2, events); 
    assert (err == CL_SUCCESS); 

    for (size_t index = 0; index < buffer_size; ++index) 
    { 
     if (data_input[index] != data_output[index]) 
     { 
      std::cerr << "Error, values differ (at index " << index << ")." << std::endl; 
      break; 
     } 
    } 

    cl_ulong time_start, time_end; 
    double  total_time; 

    clGetEventProfilingInfo(events[0], CL_PROFILING_COMMAND_START, sizeof(time_start), &time_start, NULL); 
    clGetEventProfilingInfo(events[0], CL_PROFILING_COMMAND_END, sizeof(time_end), &time_end, NULL); 
    total_time = time_end - time_start; 
    std::cout << "clEnqueueNDRangeKernel execution time in milliseconds: " << (total_time/1000000.0) << " ms" << std::endl; 
    clGetEventProfilingInfo(events[1], CL_PROFILING_COMMAND_START, sizeof(time_start), &time_start, NULL); 
    clGetEventProfilingInfo(events[1], CL_PROFILING_COMMAND_END, sizeof(time_end), &time_end, NULL); 
    total_time = time_end - time_start; 
    std::cout << "clEnqueueReadBuffer execution time in milliseconds: " << (total_time/1000000.0) << " ms" << std::endl; 

    clReleaseKernel(kernel); 
    clReleaseProgram(program); 
    clReleaseMemObject(buffer_input); 
    clReleaseMemObject(buffer_output); 
    clReleaseCommandQueue(cmd_queue); 
    clReleaseContext(context); 
} 

、私はちょうど1つの配列からのOpenCL 1.1 EPを使用して別のものに* 480 640(307200)の整数をコピーしています。

私は両方のメモリバッファをホスト側から割り当て、OpenCLにそれらをホストポインタ(私が正しい場合はmemcpyを意味しない)で使用するように指示しました。ここで

は私のラップトップからの出力は、(のGeForce GTX 765メートルに取り組んで)である:ここでは

CL_DEVICE_GLOBAL_MEM_SIZE : 2094923776 bytes 
CL_DEVICE_MAX_MEM_ALLOC_SIZE : 523730944 bytes 
CL_DEVICE_MAX_WORK_GROUP_SIZE : 1024 
CL_KERNEL_WORK_GROUP_SIZE : 1024 
CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE : 32 

clEnqueueNDRangeKernel execution time in milliseconds: 0.061856 ms 
clEnqueueReadBuffer execution time in milliseconds: 0.100544 ms 

は私から出力されます。MX6q SOM(ビバンテGC2000のGPU上で作業):

CL_DEVICE_GLOBAL_MEM_SIZE : 67108864 bytes 
CL_DEVICE_MAX_MEM_ALLOC_SIZE : 33554432 bytes 
CL_DEVICE_MAX_WORK_GROUP_SIZE : 1024 
CL_KERNEL_WORK_GROUP_SIZE : 176 
CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE : 16 

clEnqueueNDRangeKernel execution time in milliseconds: 4.463 ms 
clEnqueueReadBuffer execution time in milliseconds: 7.199 ms 

が間違って何でしたか?
は私が間違ってglobal_work_sizelocal_work_size clEnqueueNDRangeKernel機能へ値を与えていたと思います。しかし、私はまだ彼らがどのように動作し、どのように計算するのかを理解できていません。私はまだそれらの値とCL_KERNEL_WORK_GROUP_SIZEの違いを理解しておらず、OpenCLコンパイラによって計算されたカーネルワークグループのサイズはどのようになっていますか? SoMとラップトップのCL_KERNEL_WORK_GROUP_SIZEが異なるのはなぜですか?私は同じカーネルを使用します。

推奨する最適化はありますか?
私に推薦する最適化があれば、感謝します!このコンテキストは、画像処理を行う方法とOpenCLで動作させるアルゴリズムを開発する方法を学ぶことです(このSoMでOpenCVを使用することはできません)。

+0

はい、間違ったグローバルサイズとローカルワークグループサイズを使用していたことに同意します。グローバルサイズは、実行するスレッドの総数です。ローカルワークグループのサイズは、共有ローカルメモリまたは他のワークグループの概念を使用している場合に適しています。あなたが初心者なら、それを無視してNULLを渡すことができます。実行時に1つを選択することができます(2の累乗や少なくともCL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLEの倍数など、素数のないグローバルサイズを使用する方が良いでしょう)。 – Dithermaster

関連する問題