"CPU OpenCL Project" 和 "GPU OpenCL Project" 的区别

6
我安装了英特尔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
 *****************************************************************************/

我按照建议运行了diff:

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行)。


5
OpenCL可以在GPU或CPU上运行代码。它运行的位置由某些函数调用的参数决定,通常是在设置过程中。我猜想这个区别就像一个函数调用的一个参数。你可以聪明地将任务分配给两者,但是天真的代码经常表现不佳,因为CPU OpenCL使用资源最好花费在GPU传输上。 - Yakk - Adam Nevraumont
1
Yakk已经说过了。我想这应该是一个答案而不是评论。@Yakk请复制粘贴到答案中 :) - Andreas Hartmann
2
@AndreasHartmann 我只是怀疑这是一个答案;我从来没有在我的生活中使用过Intel OpenCL SDK来创建OpenCL项目。我的工作流程是不同的。但我已经使用过OpenCL,并且预测了如果我要编写SDK项目生成器,我会做什么。这不是一个答案,而是一个猜测。如果有人有实际的项目生成经验,并且可以验证我是正确的(甚至生成两个项目并运行它们之间的差异),请将其发布为答案。 - Yakk - Adam Nevraumont
1
我还不知道这是否是正确答案。我可以把这两个C文件粘贴到问题中,这样一个了解OpenCL的人就可以正确回答它了... - raldone01
1个回答

2
您已经通过diff自己回答了这个问题。 在diff输出中,您可以看到一个项目使用clBuffer对象,而另一个项目使用clImage对象。
OpenCL标准中的图像支持是可选的,因此它取决于设备和驱动程序。 GPU设备可能会更好地支持图像类型,并且大多数(如果不是全部)英特尔集成GPU都支持图像类型(据我所知)。
两个代码都使用主机指针,在英特尔设备上工作得很好,因为iGPU和CPU可以访问同一内存,或者至少表现得这样。 但是,对于离散GPU,这可能并不总是最优的选择。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接