在OpenCL中为不同的数据项执行不同的任务?

时间:2014-12-03 19:04:11

标签: performance opencl

总之,我正在寻找方法来处理计算的第一步是两个计算成本昂贵的分支之间的条件分支的情况。

我实际上是在尝试实现对图像和蒙版进行操作的图形过滤器 - 蒙版是与图像大小相同的位图阵列,并且过滤器根据蒙版的值执行不同的操作。所以我基本上想为每个像素做这样的事情:

if(mask == 1) {
    foo();
} else {
    bar();
}

其中foobar都是相当昂贵的操作。据我了解,当我在GPU上运行此代码时,它必须为每个像素计算两个分支。 (如果掩码有两个以上的可能值,这会变得更加昂贵。)有什么方法可以避免这种情况吗?

我能想到的一个选择是,在主机代码中,根据该点掩码的值,将所有像素分成两个1维数组,然后在它们上面完全不同的内核;然后从两个数据集重建图像。问题在于,在我的情况下,我想迭代地运行滤波器,并且图像和掩模都随着每次迭代而改变(掩模实际上是从图像计算的)。如果我将图像分割成主机代码中的两个桶,我必须从GPU转移图像和掩码的每次迭代,然后将新的桶转回GPU,引入新的瓶颈来替换旧的桶。

还有其他方法可以避免这个瓶颈吗?

2 个答案:

答案 0 :(得分:1)

另一种方法可能是使用掩码在每个工作组中进行简单的桶排序。

因此为每个掩码值添加一个本地内存数组和原子计数器。首先为每个工作项读取一个像素(或一组像素可能更好),增加适当的原子数并将像素地址写入数组中的该位置。

然后执行工作组障碍。

然后作为最后阶段,为每个阵列分配一些工作项(可能是底层矢量大小的倍数)并迭代它。然后,您的操作将在很大程度上有效,除非在末端有一些损失,如果您查看每个工作项目的足够像素,即使您将整个组分配给一个掩码值然后另一个掩码值,您也可能几乎没有效率损失。转动。

鉴于您的描述只有两个掩码值,将两个数组拟合到本地内存应该非常简单并且可以很好地扩展。

答案 1 :(得分:0)

将线程的要求任务推送到共享/本地内存(同步减慢进程)并执行轻量级任务,直到所有轻量级完成(因此慢速同步延迟被隐藏),然后执行更重的。

if(mask == 1) {
    uploadFoo();//heavy, upload to __local object[]
} else {
    processBar(); // compute until, then check for a foo() in local memory if any exists.
    downloadFoo();
}

使用生产者 - 消费者的方法可能。