Opencl 压缩缓冲区的快速算法

Opencl 压缩缓冲区的快速算法,opencl,Opencl,我正在进行图像压缩 图像I被分解为K个代码块{Bi} 每个块都有固定大小的MxN像素 每个块都是独立压缩的 具有压缩大小{Pi}的所有压缩块{Ci}存储在大小为K×M的线性缓冲器B中,其中M是大于所有大小Pi的固定大小 现在,我想将缓冲区B打包到缓冲区C中,并去掉每个压缩代码块Ci末尾的空白空间 因此,我需要一个内核,它将: 对于每个块Ci,求k

我正在进行图像压缩

图像I被分解为K个代码块{Bi}

每个块都有固定大小的MxN像素

每个块都是独立压缩的

具有压缩大小{Pi}的所有压缩块{Ci}存储在大小为K×M的线性缓冲器B中,其中M是大于所有大小Pi的固定大小

现在,我想将缓冲区B打包到缓冲区C中,并去掉每个压缩代码块Ci末尾的空白空间

因此,我需要一个内核,它将:

  • 对于每个块Ci,求k
  • 在偏移量_i处,将每个Ci的数据从B复制到C,大小为Pi

任何关于如何做到这一点的想法都将不胜感激

我理解你的问题如下: 您有一个压缩缓冲区集合,每个缓冲区具有不同的长度

最后,您需要一个没有空空间的简单megabuffer。为什么不像这样简单地将所有缓冲区存储在一个块中 -首先将缓冲区的数量N写为long值 -第二,存储长度为N的长值数组,该数组具有每个缓冲区的大小 -最后编写N个缓冲区


我不明白为什么您需要一个内核来实现这个

这里是代码片段,它(我想)进行流压缩。它包含大量的算术运算,但可以并行化到所需的度量

#include <time.h>
#include <stdio.h>
#include <stdlib.h>

typedef struct Block {
    int size;
    int buf[8];
} Block;

typedef struct BlockPos {
    int t_size; //Temporary size for compaction
    int f_size; //Actual size
    int pos;    //Position
} BlockPos;

int main()
{
    const int num_blocks = 16;
    Block blocks[num_blocks];
    BlockPos pos[num_blocks];

    srand(time(NULL));
    for (int i = 0; i < num_blocks; i++) {
        //Every block has non-zero length, that's easier
        blocks[i].size = rand() % 7 + 1;

        printf("Block %d len %d:\t", i, blocks[i].size);
        for(int j=0; j<blocks[i].size; j++){
            //Just to make print easier
            blocks[i].buf[j] = rand() % 33;
            printf("%d, ", blocks[i].buf[j]);
        }
        printf("\n");
    }

    for(int i=0; i<num_blocks; i++){
        pos[i].f_size = blocks[i].size;
        pos[i].t_size = pos[i].f_size;
        pos[i].pos = 0;
    }

    int step = 2;
    /* At every step we reduce number of blocks, being processed, two times.
     * This loop can't be done in parallel. */
    for (int count = 1; count < num_blocks; count *= 2) {

        /* All odd-numbered blocks are compacting to nearest left-side neighbour.
         * This loop can be done in parallel. */
        for (int i = count; i < num_blocks; i += step) {
            int dif = pos[i].pos;
            pos[i].pos = pos[i - count].pos + pos[i - count].t_size;
            pos[i - count].t_size += pos[i].t_size;
            dif -= pos[i].pos;

            // "Replace" previously compacted blocks
            for (int j = i+1; count > 1 && j < i+count; j++) {
                pos[j].pos = pos[j-1].pos + pos[j-1].f_size;
            }
        }
        step *= 2;
    }

    printf("\nPos,\tLen:\n");
    for(int i=0; i<num_blocks; i++){
        printf("%d,\t%d\n", pos[i].pos, pos[i].f_size);
    }

    printf("\n");
    return 0;
}
#包括
#包括
#包括
类型定义结构块{
整数大小;
int-buf[8];
}块;
类型定义结构块位置{
int t_size;//压缩的临时大小
int f_size;//实际大小
int pos;//位置
}BlockPos;
int main()
{
const int num_blocks=16;
块块[num_块];
BlockPos pos[num_blocks];
srand(时间(空));
对于(int i=0;i对于(int j=0;j,您需要访问PI的大小。
我会使用一个临时缓冲区,它的长度是块的总数。
压缩块时,将压缩块的长度存储到此临时缓冲区中。
然后,您的最新内核可以使用这个临时缓冲区来计算它必须写入最终缓冲区的地址。

出于性能原因,您可以将这个临时缓冲区复制到本地内存中(在最后一个内核中)。

因此,我需要编写一个流压缩算法

这将需要两个内核:

内核1:计算缓冲区偏移量的所有前缀和算法(也称为扫描):

该库有用OpenCL编写的扫描算法,OpenCL是我的目标GPGPU语言


内核2:每个工作组使用内核1中计算的偏移量从输入缓冲区进行联合读取,并将数据写入输出缓冲区。

如果您写下一个独立的(完全指定的)文件,可能会有很大帮助描述你想要一个算法做什么,而不是让描述与数据的来源纠缠在一起。如果你想搜索它,这叫做流压缩。这是一个在并行算法中经常使用的原语。谢谢,Momotapa!给它起个名字很有帮助。谢谢,Christian。当然我可以做什么您建议,但这是一种非常串行的方式;我对它的速度感兴趣。因此,使用大规模并行GPU来加快速度。算法中最“昂贵”的任务应该是复制缓冲区数据。当然,图形内存相当快(DDR5与DDR3相比),但我不明白以前为什么要将数据复制到opencl内存。数据已经在gpu上;我正在尝试减少通过PCI总线传输回主机的数据量