Python Pyopencl write_imagef函数似乎不会更改image2d_t对象

Python Pyopencl write_imagef函数似乎不会更改image2d_t对象,python,opencl,pyopencl,Python,Opencl,Pyopencl,我一直在尝试学习OpenCL,但遇到了一个小问题。在下面的代码中,我创建了一个空的只写opencl图像对象,并尝试让一个简单的内核变为黑色(或者至少以某种方式更改它),但是它只返回一个空图像。(我正在做一个图像卷积练习,它不断返回一个空图像,下面的代码只是试图隔离问题。) 我已经胡闹了两个多小时了,我很确定我被卡住了 import matplotlib.pyplot as plt import scipy.ndimage as si import pyopencl as cl import nu

我一直在尝试学习OpenCL,但遇到了一个小问题。在下面的代码中,我创建了一个空的只写opencl图像对象,并尝试让一个简单的内核变为黑色(或者至少以某种方式更改它),但是它只返回一个空图像。(我正在做一个图像卷积练习,它不断返回一个空图像,下面的代码只是试图隔离问题。)

我已经胡闹了两个多小时了,我很确定我被卡住了

import matplotlib.pyplot as plt
import scipy.ndimage as si
import pyopencl as cl
import numpy as np
import os

kernel = """
__kernel void black(__write_only image2d_t dst,
                    int rows,
                    int columns)
{
    const int column = get_global_id(0);
    const int row = get_global_id(1);

        if (column < columns && row < rows)
        {
            write_imagef(dst, (int2)(column, row),
                (float4)(1.0f, 1.0f, 1.0f, 1.0f));
        }   
}
"""

ctx = cl.create_some_context()
queue = cl.CommandQueue(ctx)

mf = cl.mem_flags

f = cl.ImageFormat(cl.channel_order.R, cl.channel_type.UNSIGNED_INT8)

dst_image = cl.Image(ctx, mf.WRITE_ONLY , f, shape=(100,100,4))

prg = cl.Program(ctx, kernel).build()

prg.black(queue, (100,100), None, dst_image,
          np.int32(100),
          np.int32(100))

postimage = np.zeros((100,100,4), dtype=np.uint8)
cl.enqueue_copy(queue, postimage, dst_image,
                origin=(0, 0, 0),
                region=(100,100,4))

plt.imshow(postimage)
plt.show()
导入matplotlib.pyplot作为plt
将scipy.ndimage导入为si
将pyopencl作为cl导入
将numpy作为np导入
导入操作系统
kernel=”“”
__内核无效黑色(uuu只写图像2D_ut dst,
int行,
int列)
{
const int column=get_global_id(0);
const int row=get_global_id(1);
if(列<列和行<行)
{
写入图像F(dst,(int2)(列,行),
(浮动4)(1.0f、1.0f、1.0f、1.0f));
}   
}
"""
ctx=cl.创建一些上下文()
queue=cl.CommandQueue(ctx)
mf=cl.mem_标志
f=cl.ImageFormat(cl.channel\u order.R,cl.channel\u type.UNSIGNED\u INT8)
dst_image=cl.image(仅限ctx、mf.WRITE_、f、shape=(100100,4))
prg=cl.Program(ctx,kernel.build())
prg.黑色(队列,(100100),无,dst_图像,
np.int32(100),
np.int32(100))
postimage=np.Zero((100100,4),dtype=np.uint8)
cl.enqueue_副本(队列、后期图像、dst_图像、,
原点=(0,0,0),
地区=(100100,4))
plt.imshow(后期图像)
plt.show()

您的内核代码实际上很好(尽管您发布的代码将每个像素设置为白色,因此很难判断它是否工作!)。问题在于您创建图像的方式。当您在
cl.Image
构造函数中指定
shape=(100100,4)
时,实际上您要求的是3D图像

让示例代码产生有用内容的最简单方法是修改以下行:

f = cl.ImageFormat(cl.channel_order.R, cl.channel_type.UNSIGNED_INT8)
....
dst_image = cl.Image(ctx, mf.WRITE_ONLY , f, shape=(100,100,4))
...
cl.enqueue_copy(queue, postimage, dst_image,
                origin=(0, 0, 0),
                region=(100,100,4))

在这里,我将图像格式更改为RGBA,这与
matplotlib
图像显示函数所期望的内容相匹配(我不熟悉该库,因此可能您也可以让它显示单通道图像)。我还修改了创建图像并将其复制回宿主的线条,使其为2D,而不是3D

现在,如果更改内核以将此数据写入映像:

write_imagef(dst, (int2)(column, row), (float4)(1.0f, 0.0f, 0.0f, 1.0f));

你应该得到一个漂亮的红色输出图像

该规范规定“write_imageui只能用于使用设置为以下值之一的image_channel_data_type创建的图像对象:CL_UNSIGNED_INT8、CL_UNSIGNED_INT16或CL_UNSIGNED_INT32。”。我在列表中没有看到
CL\u UNORM\u INT8
。试着用
write\u imagef
也许吧。我试过write\u imagef和write\u imagei,都没用。
write_imagef(dst, (int2)(column, row), (float4)(1.0f, 0.0f, 0.0f, 1.0f));