C++ 如何使用c++;包装纸

C++ 如何使用c++;包装纸,c++,opencl,C++,Opencl,在CUDA中,通过在for循环中调用下面的代码,我可以启动同一内核,在同一数组的不同部分上并发操作: kernel<<<blkPerGrd, thdPerBlk, 0, stream[k]>>>(in_array + offset, out_array + out_offset) kernel.setArg(0, in_array); kernel.setArg(2, in_offset); kernel.setArg(3, out_array); kern

在CUDA中,通过在for循环中调用下面的代码,我可以启动同一内核,在同一数组的不同部分上并发操作:

kernel<<<blkPerGrd, thdPerBlk, 0, stream[k]>>>(in_array + offset, out_array + out_offset)
kernel.setArg(0, in_array);
kernel.setArg(2, in_offset);
kernel.setArg(3, out_array);
kernel.setArg(4, out_offset);
queue[k].enqueueNDRangeKernel(kernel, cl::NullRng, gblRng, lclRange, NULL, NULL);
其中
in_array
out_array
cl::Buffer
对象


这有意义吗?还是有更好的方法来处理偏移?我试着检查
cl::Buffer
类是否接受指针算法,但我认为它不接受。

将内核分解为多个部分是可以接受的方法,但还有其他方法

就个人而言,我更喜欢通过更改
enqueueNDRangeKernel
的参数来启动这类内核。您可能会注意到,您明显地留下了一个参数“null”,或者更准确地说,
cl::NullRng
。这通常是Offset参数,可以用来做你想做的事情

Image img;
std::vector<cl::Event> events;
//Do not perform work on an area larger than 100x100 pixels at a time.
for(int x = 0; x < img.width(); x += 100) {
    int end_x = std::min(img.width(), x + 100);
    for(int y = 0; y < img.height(); y += 100) {
        int end_y = std::min(img.height(), y + 100);
        events.emplace_back();
        queue.enqueueNDRangeKernel(kernel, cl::NDRange{x, y}, cl::NDRange{end_x - x, end_y - y}, {}, nullptr, &events.back());
    }
}

queue.enqueueWaitForEvents(events);
图像img;
向量事件;
//不要一次在大于100x100像素的区域上执行工作。
对于(int x=0;x
事实上,我认为你的方法更好。我的是不可接受的,因为显然,您不能在内核运行时设置它的参数(参见此处)。当我运行我的代码时,我根本不会得到内核重叠。我会试试你的方法@Damian我认为这篇文章有一个误解:你可以在内核运行时设置内核参数;这些更改不会影响已经在队列中或正在运行的任何内核:它们只会影响尚未排队的内核。我很确定我编写的代码与您在过去多次编写的代码类似。特别是因为你显然在使用多个队列。哈,这很有趣。我正在按照我描述的方式运行内核,它们似乎是按顺序执行的。我在设置参数和内核排队上有一个for循环。最后,我有一个for循环调用
队列[I].flush()
队列[I].finish()
命令,等待它们全部完成。即使内核对所有东西都是一样的,这是否应该起作用?因为我甚至尝试过创建多个内核对象(在一个向量中),但这并没有什么不同。@Damian,那是另一回事。必须明确指示队列在创建时允许“无序执行”。默认的OpenCLAPI行为是队列按照提交的顺序执行指令。查看或查看命令队列创建。