【发布时间】:2021-09-14 17:55:51
【问题描述】:
对于我编写的 OpenCL 程序,我需要对灰度图像进行计算。这些灰度图像以 .pgm 格式存储,我将它们作为浮点向量读入我的程序。
据我了解 image2d_t 内存对象,每个像素都被编码为具有 4 个组件的 OpenCL 矢量数据类型,例如float4 与我的情况一样,其中组件 1 到 3 对 3 个颜色通道 R、G、B 中的颜色值进行编码,第四个组件对亮度或 alpha 进行编码。因此,我尝试炸毁现有图像以将其读入 image2d_t 内存对象,如下所示:
std::vector<float> A(256,0.0);
std::vector<float> A_img(1024, 0.0);
for(int i=0; i<256; i++)
{
A_img[4*i] = A[i];
A_img[(4*i)+3] = 1;
}
稍后在将此向量复制到 image2d_t 对象的过程中,我的设备的小端序可能会导致组件 1 和 4 被切换。我不确定。
但是,当将此图像写入我的 GPU 内存、让内核读取它、将其写入输出图像并从 GPU 内存读回时,我无法取回该图像。一个最小的工作示例(对于 OpenCL 来说总是有点长)如下:
#define CL_HPP_TARGET_OPENCL_VERSION 120
#define CL_HPP_MINIMUM_OPENCL_VERSION 120
#if defined(__APPLE__)
#include <OpenCL/cl2.hpp>
#else
#include <CL/cl2.hpp>
#endif
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
int main(void)
{
// Set up platform, device and context
std::vector<cl::Platform> platforms;
std::vector<cl::Device> devices;
cl::Device default_device;
cl::Platform::get(&platforms);
if (platforms.size() == 0)
{
std::cout << "No OpenCL platform found, check installation!" << std::endl;
exit(-1);
}
platforms[0].getDevices(CL_DEVICE_TYPE_ALL, &devices);
if (devices.size() == 0)
{
std::cout << "No devices found in platform, check installation!" << std::endl;
exit(-1);
}
default_device = devices[0];
cl::Context context(default_device);
std::ifstream program_file("read_write_image.cl");
std::string program_string(std::istreambuf_iterator<char>(program_file), (std::istreambuf_iterator<char>()));
cl::Program::Sources source { program_string };
cl::Program dummy_program(context, source);
if (dummy_program.build()!=CL_SUCCESS)
{
std::cout << "Error building: " << dummy_program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(default_device)<< std::endl;
exit(-1);
}
cl::Kernel kernel(dummy_program, "read_write_image");
cl::CommandQueue queue(context, default_device);
// Set up dummy grayscale image
std::vector<float> A(256, 0.0);
for(int i=0; i<256; i++)
{
A[i] = 255.0f - i;
std::cout << A[i] << " ";
}
std::cout << std::endl;
// Blow up to float4 array
std::vector<float> A_img(1024, 0.0);
for(int i=0; i<256; i++)
{
A_img[4*i] = A[i];
A_img[(4*i)+3] = 1;
}
std::vector<float> B_img(1024, 0.0);
cl::ImageFormat grayscale(CL_R, CL_FLOAT);
cl::Image2D Input_Image(context, CL_MEM_READ_ONLY, grayscale, 16, 16);
cl::Image2D Output_Image(context, CL_MEM_WRITE_ONLY, grayscale, 16, 16);
std::array<cl::size_type, 3> origin {0,0,0};
std::array<cl::size_type, 3> region {16, 16, 1};
queue.enqueueWriteImage(Input_Image, CL_TRUE, origin, region, 0, 0, &A_img[0]);
kernel.setArg(0, Input_Image);
kernel.setArg(1, Output_Image);
queue.enqueueNDRangeKernel(kernel, cl::NullRange, cl::NDRange(16,16), cl::NullRange, NULL);
queue.enqueueReadImage(Output_Image, CL_TRUE, origin, region, 0, 0, &B_img[0]);
for(int i=0; i<1024; i++)
{
std::cout << B_img[i] << " ";
}
std::cout << std::endl;
return EXIT_SUCCESS;
}
内核代码(要放在“read_write_image.cl”文件中)如下:
__constant sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE|CLK_ADDRESS_CLAMP|CLK_FILTER_LINEAR;
__kernel void read_write_image(read_only image2d_t input_image, write_only image2d_t output_image)
{
int i = get_global_id(0);
int j = get_global_id(1);
float tmp = read_imagef(input_image, sampler, (int2) (i,j)).x;
write_imagef(output_image, (int2) (i,j), (float4) (tmp,0,0,1));
}
这个最小的工作示例生成一个 16x16 的图像 A,它被解释为灰度图像,从左上角以白色像素开始,到右下角以黑色像素结束,然后读回图像 B我的系统完全是黑色的,即只有零。我在什么时候会出错?
【问题讨论】:
标签: c++ image image-processing opencl gpgpu