【问题标题】:Difference between "CPU OpenCL Project" and "GPU OpenCL Project"“CPU OpenCL 项目”和“GPU OpenCL 项目”的区别
【发布时间】:2018-12-10 16:05:11
【问题描述】:

我安装了英特尔 OpenCL SDK 并想创建一个项目。 Visual Studio 2017 向我展示了这两个选项和第三个“空 OpenCL 项目”。我不知道这两者有什么区别。我试图查看模板代码,但由于我(还)不了解 OpenCL,因此无法理解它们的区别。

许可证头:

/*****************************************************************************
 * Copyright (c) 2013-2016 Intel Corporation
 * All rights reserved.
 *
 * WARRANTY DISCLAIMER
 *
 * THESE MATERIALS ARE PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THESE
 * MATERIALS, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Intel Corporation is the author of the Materials, and requests that all
 * problem reports or change requests be submitted to it directly
 *****************************************************************************/

我按照建议运行了一个差异:

625,629c625,626
<     // Create new OpenCL buffer objects
<     // As these buffer are used only for read by the kernel, you are recommended to create it with flag CL_MEM_READ_ONLY.
<     // Always set minimal read/write flags for buffers, it may lead to better performance because it allows runtime
<     // to better organize data copying.
<     // You use CL_MEM_COPY_HOST_PTR here, because the buffers should be populated with bytes at inputA and inputB.
---
>     cl_image_format format;
>     cl_image_desc desc;
631c628,650
<     ocl->srcA = clCreateBuffer(ocl->context, CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, sizeof(cl_uint) * arrayWidth * arrayHeight, inputA, &err);
---
>     // Define the image data-type and order -
>     // one channel (R) with unit values
>     format.image_channel_data_type = CL_UNSIGNED_INT32;
>     format.image_channel_order     = CL_R;
> 
>     // Define the image properties (descriptor)
>     desc.image_type        = CL_MEM_OBJECT_IMAGE2D;
>     desc.image_width       = arrayWidth;
>     desc.image_height      = arrayHeight;
>     desc.image_depth       = 0;
>     desc.image_array_size  = 1;
>     desc.image_row_pitch   = 0;
>     desc.image_slice_pitch = 0;
>     desc.num_mip_levels    = 0;
>     desc.num_samples       = 0;
> #ifdef CL_VERSION_2_0
>     desc.mem_object        = NULL;
> #else
>     desc.buffer            = NULL;
> #endif
> 
>     // Create first image based on host memory inputA
>     ocl->srcA = clCreateImage(ocl->context, CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, &format, &desc, inputA, &err);
634c653
<         LogError("Error: clCreateBuffer for srcA returned %s\n", TranslateOpenCLError(err));
---
>         LogError("Error: clCreateImage for srcA returned %s\n", TranslateOpenCLError(err));
638c657,658
<     ocl->srcB = clCreateBuffer(ocl->context, CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, sizeof(cl_uint) * arrayWidth * arrayHeight, inputB, &err);
---
>     // Create second image based on host memory inputB
>     ocl->srcB = clCreateImage(ocl->context, CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, &format, &desc, inputB, &err);
641c661
<         LogError("Error: clCreateBuffer for srcB returned %s\n", TranslateOpenCLError(err));
---
>         LogError("Error: clCreateImage for srcB returned %s\n", TranslateOpenCLError(err));
645,649c665,666
<     // If the output buffer is created directly on top of output buffer using CL_MEM_USE_HOST_PTR,
<     // then, depending on the OpenCL runtime implementation and hardware capabilities, 
<     // it may save you not necessary data copying.
<     // As it is known that output buffer will be write only, you explicitly declare it using CL_MEM_WRITE_ONLY.
<     ocl->dstMem = clCreateBuffer(ocl->context, CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR, sizeof(cl_uint) * arrayWidth * arrayHeight, outputC, &err);
---
>     // Create third (output) image based on host memory outputC
>     ocl->dstMem = clCreateImage(ocl->context, CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR, &format, &desc, outputC, &err);
652c669
<         LogError("Error: clCreateBuffer for dstMem returned %s\n", TranslateOpenCLError(err));
---
>         LogError("Error: clCreateImage for dstMem returned %s\n", TranslateOpenCLError(err));
734c751,755
<     cl_int *resultPtr = (cl_int *)clEnqueueMapBuffer(ocl->commandQueue, ocl->dstMem, true, CL_MAP_READ, 0, sizeof(cl_uint) * width * height, 0, NULL, NULL, &err);
---
>     size_t origin[] = {0, 0, 0};
>     size_t region[] = {width, height, 1};
>     size_t image_row_pitch;
>     size_t image_slice_pitch;
>     cl_int *resultPtr = (cl_int *)clEnqueueMapImage(ocl->commandQueue, ocl->dstMem, true, CL_MAP_READ, origin, region, &image_row_pitch, &image_slice_pitch, 0, NULL, NULL, &err);
783c804
<     cl_device_type deviceType = CL_DEVICE_TYPE_CPU;
---
>     cl_device_type deviceType = CL_DEVICE_TYPE_GPU;

我也可以粘贴两个完整的源文件,但它们很长(900 行)。

【问题讨论】:

  • OpenCL 可以在 GPU 或 CPU 上运行代码。它运行的是由某些函数调用的一些参数决定的,通常是在设置期间。我猜想区别就像一个函数调用的一个参数。 (您可以花哨并为两者分配任务;执行此操作的幼稚代码通常表现不佳,因为 cpu openCL 使用的资源更好地用于 gpu 编组)
  • 好吧 Yakk 说的。我想这应该是一个答案而不是评论。 @Yakk 请将其复制粘贴到答案中:)
  • @AndreasHartmann 我只是怀疑这是一个答案;我一生中从未真正使用过英特尔 OpenCL SDK 来创建 OpenCL 项目。我的工作流程不同。但是我使用过 OpenCL,并且我预计如果我要编写 SDK 项目生成器我会做什么。这与其说是一个答案,不如说是一个猜测。如果有人在实际项目生成方面有实际经验并且完全可以验证我是对的(见鬼,生成两个项目并在它们之间运行差异),请将其发布为答案。
  • 我还不知道这是否是正确的答案。我可以将两个 c 文件粘贴到问题中。所以懂OpenCL的人可以正确回答...

标签: c++ opencl


【解决方案1】:

您已经用差异自己回答了这个问题。 在 diff 输出中,您可以看到一个项目使用 clBuffer 对象,而另一个项目使用 clImage。

图像支持在 OpenCL 标准中是可选的,因此它取决于设备和驱动程序。 GPU 设备在图像类型方面可能具有更好的性能,而且大多数(如果不是全部)英特尔集成 GPU 都支持图像类型 (AFAIK)。

两个代码都使用主机指针,这在 Intel 设备上运行良好,因为 iGPU 和 CPU 可以寻址相同的内存,或者至少以这种方式运行。但是,这对于离散 GPU 而言可能并不总是最佳的。

【讨论】:

    猜你喜欢
    • 2012-12-23
    • 1970-01-01
    • 2011-07-23
    • 2013-05-02
    • 1970-01-01
    • 2018-07-21
    • 1970-01-01
    • 2012-01-25
    • 2019-11-13
    相关资源
    最近更新 更多