0

我正在学习 OpenCL 中的内存缓冲区和图像。据我了解,OpenCL 中的图像只是一种抽象数据结构,与类似照片的图像(x、y、r、g、b 或 x、y、h、s、l、a , 管他呢)。

在我正在阅读的这本书中,它们提供了一个从 HDD 读取 .bmp 文件并将其转换为浮点数组的函数

然后他们将浮点数组写入 cl_mem 变量:

// GET THE .BMP AS A FLOAT[]
float* inputImage = readImage(inputFile, &imageWidth, &imageHeight);

// DEFINE THE IMAGE AND FORMAT 
cl_image_desc desc;
desc.image_type = CL_MEM_OBJECT_IMAGE2D;
desc.image_width = imageWidth;
desc.image_height = imageHeight;
desc.image_depth = 0;
desc.image_array_size = 0;
desc.image_row_pitch = 0;
desc.image_slice_pitch = 0;
desc.num_mip_levels = 0;
desc.num_samples = 0;
desc.buffer = NULL;
cl_image_format format;
format.image_channel_order = CL_R;     
format.image_channel_data_type = CL_FLOAT; 

// DEFINE AND WRITE THE IMAGE
cl_mem d_inputImage = clCreateImage(context, CL_MEM_READ_ONLY, &format, &desc, NULL, NULL);
ize_t origin[3] = { 0, 0, 0 };  
size_t region[3] = { imageWidth, imageHeight, 1 }; 
clEnqueueWriteImage(queue, d_inputImage, CL_FALSE, origin, region, 0, 0, inputImage, 0, NULL, NULL);

那么这是否告诉 OpenCL 我们正在处理类似照片的图像,或者我们只是定义了一个数据结构?在本书的内核中,他们使用:

// sourceImage is d_inputImage from the previous block of code. its type is image2d_t
float4 pixel;
pixel = read_imagef(sourceImage, sampler, coords);
sum.x += pixel.x * filter[filterIdx++];

OpenCL 只是松散地将这些数据结构用作类似照片的图像,还是以任何类似于 .NET 的方式,您可以从许多不同的来源创建位图对象,然后一旦有了该对象,您就可以用它做任何您想做的事情?

4

2 回答 2

2

OpenCL 有位图的概念吗?

当然; cl_image_desc类型(连同它的)cl_image_format代表一个图像(或位图)。如果您将代码示例中设置的属性或字段与Bitmap类的属性进行比较,您会发现它们几乎相同,可能只是命名略有不同:

真正的区别在于 OpenCL 只关心内存中的图像,并快速有效地处理这些图像。OpenCL 不关心 I/O、文件格式、编解码器等。

那么这是否告诉 OpenCL 我们正在处理类似照片的图像,或者我们只是在定义一个数据结构?

是的。cl_image_desc完全描述了如何解释内存中的图像数据。这对应于您的处理内核处理此数据的方式(例如灰度或单通道图像、RGBA 等)。您可以将类似照片的图像视为内存中的二进制数据块,其中包含所有这些额外的元数据,可以将其理解为类似照片的图像。所以它在某种意义上是一个简单缓冲区(或cl_buffer)的超集。

OpenCL 只是松散地将这些数据结构用作类似照片的图像,还是以任何类似于 .NET 的方式,您可以从许多不同的来源创建位图对象,然后一旦有了该对象,您就可以用它做任何您想做的事情?

OpenCL 的范围是为跨平台 API 中数据的高性能异构(即 CPU 和 GPU)处理提供框架。它并不是想成为一个像 .NET 这样的完整平台,它还提供文件 I/O、图形渲染等。OpenCL 的想法是它适合您已经使用的任何平台代码。您使用您的平台代码(.NET、Cocoa、libjpeg 或其他)将文件加载到内存中,从您碰巧使用的任何磁盘表示和编解码器进行解码。然后你可以将这些数据传递给 OpenCL,通过这些结构来描述它,进行处理。

一旦它们在内存中,您就可以有效地从任何这些相同的源创建 OpenCL 图像。运行完处理内核后,您可以从 OpenCL 结构中取出数据并将结果传递给其余代码,并使用平台 API 将结果呈现给屏幕或将它们保存为编码文件。

于 2013-08-07T22:47:58.497 回答
1

是和否:

OpenCL 有位图的概念吗?

不,作为实际的位图 (c)(R)(tm) 图像文件格式,但它在内存中具有位图(图像)的一般抽象/概念。后者与前者不一样!文件格式是一个简单的 RIFF 资源容器,而后者是一个笼统的概念。

它是否以任何方式类似于 .NET,您可以在其中从许多不同的来源创建位图对象

不,您不能简单地读取或写入各种文件格式。

OpenCL 是否只是松散地使用这些数据结构作为类似照片的图像

是的(有点,多一点)。

OpenCL确实知道内存中的 RAW 图像格式,但支持不包括 PNG、JPG 或其他实际文件格式。OpenCL没有像.NET Class Library. (但这是正确的,因为它根本不是OpenCL目标或角色。在这方面没有可比性,它们是完全不同的动物。OpenCL.NET

.NET 可以读取和写入许多不同的文件格式。一旦它们在内存OpenCL中,就可以处理各种RAW 格式(不同的 RGB 顺序和位深度) 。但您的任务是找到如何从/向实际文件读取/写入 RAW 数据的方法:OpenCL 不支持 JPG、PNG、GIF 或其他开箱即用的压缩和文件格式。例如,如果你想读/写,那么你可以使用libjpeg,类似地使用libpng,等等。这些库都是开源的,这就是整个生态系统的结合方式。JPEGPNG

这可能也是本书提供了一个简单的例程来读取和写入非常小的BMP原始格式子集的原因。(位图可以有几种颜色深度、RLE压缩等)。所以请记住,本书例程只能处理BMP. 我建议PNG在现实世界的情况下,因为 RAW 数据会占用惊人的巨大空间,这会降低性能(当然,压缩运行时本身需要权衡)。本书的套路还有一件事:它是为OpenCL内核需求量身定做的,它提供了浮点数组,而且它只有一个通道(format.image_channel_order = CL_R;)。您通常会从图像库中接收整数RGB颜色通道组件。但是将其转换为浮点数并不是什么大问题(除非您有大量数据)。

于 2013-08-07T22:21:55.863 回答