OpenCL中的便携式矢量移位/排列?

Posted

技术标签:

【中文标题】OpenCL中的便携式矢量移位/排列?【英文标题】:Portable vector shift/permutation in OpenCL? 【发布时间】:2020-07-19 11:54:50 【问题描述】:

我正在尝试编写一个修剪过的平均内核,它将一组帧(~100)作为输入。我正在考虑使用插入排序(大小约为 8)。这意味着我需要从输入图像中一次读取一个 float/uint/ushort 并将其与 8 宽向量进行比较,将元素向上移动并在正确的位置插入新值(如有必要),与平均值相加的最大值。

我很难找到一种可移植的方式来移动向量中的元素并将新元素插入到正确的位置。例如,我知道 AMD GPU 具有 ds_permute,但它们不是可移植的,而且我想不出一种使用算术和关系运算符的聪明方法(因为那些只在他们的通道上运行,而 AFAIK 未对齐的向量访问是 UB在 OpenCL 中)。

【问题讨论】:

【参考方案1】:

如果您的列表中只有 8 个项目,那么您可以添加一些间接并有一个索引表 uchar[8]。您为预排序的元素分配值 0-7。当您执行排序时,您不会重新排列这些项目,而是将它们的索引插入到表中。

为了获得加速,您需要使用 4 位存储每个索引,以使所有 8 位都适合 32 位字。老实说,我认为在你的情况下这不会更快。

float elements[8];
uint index_table = 0;
uint sorted_size = 0;

// insert elements[i]
void insert(uint i)

    uint temp = index_table
    for (j = 0; j < sorted_size ; ++j)
    
        if (elements[i] < elements[temp & 0xf])
        
            // Insert i
            temp = (temp << 4) | i;
            index_table = (index_table & (4 * j - 1)) | (temp << (4 * j));
            return;
        
        temp >>= 4;
    

    // Insert at end
    index_table  |= i << 4 * sorted_size ;


void insertion_sort()

    // We can skip the first iteration since the 1st element is always inserted at the start
    for (sorted_size = 1; sorted_size < 8; ++sorted_size)
    
        insert(sorted_size);
    


float ith_smallest(uint i)

    return elements[(index_table >> 4 * i) & 0xf]; 

【讨论】:

嗯,不。我在列表中有大约 100 个元素(所以没有 4 位索引)。我需要对除最小和最大的 8 之外的所有元素求和(即对 84 个中间元素求和)。重点是进行矢量化排序(8 宽浮点矢量非常适合现代 simd 单元),因此可以在大约 10 分钟内使用合理的硬件堆叠 10k 批次的 100 个 8Mpx 图像。

以上是关于OpenCL中的便携式矢量移位/排列?的主要内容,如果未能解决你的问题,请参考以下文章

内存中的高效矢量位数据“旋转”/“重新排列”[例如在 Python 中,Numpy] [关闭]

矢量调整大小 - 检测的便携方式

Cloo 中的 OpenCL 扩展

GPU 中的并行性 - CUDA / OpenCL

OpenCL 中的私有内存是不是有最大限制?

OpenCL 中的全局内存是不是连续