【问题标题】:OpenCL device side enqueue kernel & local memoryOpenCL 设备端入队内核和本地内存
【发布时间】:2015-03-27 14:41:04
【问题描述】:

我正在尝试在设备端排队内核中使用本地内存。

我假设任何本地声明的数组在工作组中的所有工作项中都是可见的。 当我在从主机端调用的内核上使用本地内存时,这被证明是正确的,但是当我在设备端排队的内核上使用类似的设置时,我遇到了问题。

我的假设有问题吗?

编辑:
我的内核如下: 我的目标是将 FIFO 管道分类为 3 个缓冲区。问题是我的工作项的视图范围有限,我正在尝试将缓冲区写入另一个管道。

int pivot;

int in_pipe[BIN_SIZE];
int lt_bin[BIN_SIZE];
int gt_bin[BIN_SIZE];
int e_bin[BIN_SIZE];


reserve_id_t down_id = work_group_reserve_read_pipe(down_pipe, local_size);
//while ( is_valid_reserve_id(down_id) == false){
//  down_id = work_group_reserve_read_pipe(down_pipe, local_size);
//}
//in_bin[tid] = -5;
if( is_valid_reserve_id(down_id) == true){
    int status = read_pipe(down_pipe, down_id, lid, &pipe_out);
    work_group_commit_read_pipe(down_pipe, down_id);

    pivot = pipe_out;
    pivot = work_group_broadcast(pivot, 0); 

    work_group_barrier(CLK_GLOBAL_MEM_FENCE);
    work_group_barrier(CLK_LOCAL_MEM_FENCE);    
    in_pipe[tid] = pipe_out;        
    //in_bin[lid] = in_pipe[tid];

    int e_count = 0;
    int gt_count = 0;
    int lt_count = 0;       

    if(in_pipe[tid] == pivot){
        e_count = 1;
    }
    else if(in_pipe[tid] < pivot){
        lt_count = 1;
    }
    else if(in_pipe[tid] > pivot){
        gt_count = 1;
    }

    int e_tot = work_group_reduce_add(e_count);
    e_tot = work_group_broadcast(e_tot, 0);
    int e_val = work_group_scan_exclusive_add(e_count);     

    int gt_tot = work_group_reduce_add(gt_count);
    gt_tot = work_group_broadcast(gt_tot, 0);
    int gt_val = work_group_scan_exclusive_add(gt_count);   

    int lt_tot = work_group_reduce_add(lt_count);
    lt_tot = work_group_broadcast(lt_tot, 0);
    int lt_val = work_group_scan_exclusive_add(lt_count);           

    //in_bin[tid] = lt_val;
    work_group_barrier(CLK_GLOBAL_MEM_FENCE);
    work_group_barrier(CLK_LOCAL_MEM_FENCE);

    if(in_pipe[tid] == pivot){
        e_temp[e_val] = in_pipe[tid];
        //in_bin[e_val] = e_bin[e_val];
        //e_bin[e_Val] = work_group_broadcast(e_bin[e_val], lid);
    }
    if(in_pipe[tid] < pivot){
        lte_temp[lt_val] = in_pipe[tid];
        //in_bin[lt_val] = lt_bin[lt_val];
    }
    if(in_pipe[tid] > pivot){
        gt_bin[gt_val] = in_pipe[tid];
        //in_bin[gt_val] = gt_bin[gt_val];
    }

【问题讨论】:

    标签: c opencl


    【解决方案1】:

    不,没有错。局部变量也在整个工作组设备端声明和使用。但是,它们不会与父内核共享。

    你到底在做什么?

    【讨论】:

    • 这是 OpenCL 2.0,以防不明确。我正在获取管道的内容,并且正在尝试对本地数组执行特定的写入。据我所见,从我与之交互的方式来看,单个工作项只能看到 FIFO 管道的 1 个元素。我已经声明了 3 个数组,并且我正在根据弹出的结果写入这些数组上的特定位置,基本上将 FIFO 管道分类到 3 个 bin 中。
    • 您应该能够在工作项中看到多个管道元素,但管道中没有顺序,因此您无法保证哪个工作项将获得哪个值。我不确定你的代码是本地内存。代码看起来不错。您不必在工作组功能周围使用障碍,但这不会破坏它。
    • 我的问题更多是关于管道的能力和局限性,即管道基础设施。我想用管道创建一个动态树结构,其中涉及分支和设备端管道创建。管道是内存对象,就像缓冲区一样,目前还不能在设备端创建。从我在 AMD 演示代码中看到的情况来看,管道可以做的最好的事情是形成一个长链,通过将 __read_only 与 __write_only 交换,在每个阶段重用管道,反之亦然。
    • 我还必须反驳管道没有顺序的说法。可以在 write_pipe 调用中使用索引作为写入顺序。当然,我很想在这两个方面都被证明是错误的。
    • 预订之间没有订单。在预留中,您可以使用索引来寻址,但它受预留中数据包数量的限制。你是对的,你不能在设备端分配管道,但你可以传递它们。请注意正确排序子内核,因为管道不支持并发读写。
    【解决方案2】:

    我的问题的有效解决方案是:

    无法在设备端创建管道。我试图完成的是制作一个动态的树结构,包括分支。 OpenCL 管道根本无法做到这一点,因为管道仍然是在主机端创建的内存对象。目前规范中没有创建内存对象的方法。

    然而,管道可以用于动态递归方法,尽管递归不能偏离,并且必须以线性方式发生。有关详细信息,请参阅 AMD APP SDK 示例代码包中的示例代码。具体请看 Device Enqueue BFS 示例。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-07-25
      • 2011-10-08
      • 1970-01-01
      • 2017-03-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多