【问题标题】:Does OpenCL support a randomly accessed global queue buffer?OpenCL 是否支持随机访问的全局队列缓冲区?
【发布时间】:2014-04-10 09:58:49
【问题描述】:

我正在编写一个处理组合数据的内核。因为这类问题通常有很大的问题空间,大部分处理的数据都是垃圾,有没有办法可以做到以下几点:

(1) 如果计算出的数据通过某种条件,则将其放入全局输出缓冲区。

(2) 一旦输出缓冲区满了,就将数据发送回主机

(3) 主机从缓冲区中取出一份数据并清除

(4) 然后创建一个新的缓冲区供GPU填充

为了简单起见,这个例子可以说是一个选择性内积,我的意思是

__global int buffer_counter; // Counts 

void put_onto_output_buffer(float value, __global float *buffer, int size)
{
    // Put this value onto the global buffer or send a signal to the host
}

__kernel void
inner_product(
    __global const float *threshold,       // threshold
    __global const float *first_vector,    // 10000 float vector
    __global const float *second_vector,   // 10000 float vector
    __global float *output_buffer,         // 100 float vector
    __global const int *output_buffer_size // size of the output buffer -- 100
{
    int id = get_global_id(0);
    float value = first_vector[id] * second_vector[id];
    if (value >= threshold[0])
        put_onto_output_buffer(value, output_buffer, output_buffer_size[0]); 
}

【问题讨论】:

    标签: c kernel opencl


    【解决方案1】:

    这取决于输出的频率。如果它是高频率的(一个工作项经常写入输出),那么buffer_counter 将成为争用的来源并导致速度变慢(顺便说一下,它需要使用原子方法进行更新,即为什么它很慢)。在这种情况下,您最好始终编写输出并稍后对真实输出进行排序。

    另一方面,如果写入输出相当少见,那么使用原子位置指示符是很有意义的。大多数工作项将进行计算,决定它们没有输出,然后退出。只有不经常有输出的那些才会竞争原子输出位置索引,串行递增它,并将它们的输出写入它们的唯一位置。您的输出内存将紧凑地包含结果(没有特定的顺序,因此如果您关心,请存储工作项 ID)。

    再次,请阅读原子,因为索引需要是原子的。

    【讨论】:

    • 如何从主机中的缓冲区进行多次读取?
    • 您可以根据需要随时读取缓冲区,但是主机必须映射它(使用clEnqueueMapBufer)以获取指向它的指针,并且您不能将任何使用它的内核排入队列主机已映射。当你读完它(尽可能多地),取消映射,然后你可以在它上面运行更多的内核(如果你愿意的话)。
    • 另外,内核如何知道主机何时完成了从缓冲区的读取?或者,这是一个阻塞操作?
    • 内核不“知道”,你必须正确排序:1. clEnqueueMapBuffer(带阻塞),2. 在主机上尽可能多地使用它,3. clEnqueueUnmapMemObject,4 .clEnqueueNDRangeKernel
    • 你知道这样做的例子吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-11
    • 2014-09-13
    • 1970-01-01
    • 2020-02-14
    • 2012-09-04
    相关资源
    最近更新 更多