压缩二进制数组以克服GPU内存限制 行程编码获得O1随机访问权限确定Olog n随机访问

问题描述

我正在GPU(CUDA)上进行物理仿真,并在标准图形卡上的有限可用内存中苦苦挣扎。

问题如下:

我有一个巨大的二进制掩码(> 30 GB),可以用作查找表。为了评估特定变量的有效性,我从变量属性中生成了一个索引,并对照查找表进行检查。在GPU上同时为数百万个变量并行完成此操作(仅需要读取访问权限)。

为了最小化此二进制掩码的大小以使其适合GPU内存,我正在寻找压缩技术,该技术仍可以通过对基础数据建立索引来实现快速访问(最好由负责所有事务的透明容器类)。由于掩码本身包含多个重复的单个位,因此我也希望可以实现较高的压缩率。

所以我的问题是:

nvidia的CUDA实施中是否已有已知方法? 还有其他默认的C ++库可以做到这一点吗?

解决方法

行程编码

我不知道有哪个库可以为您执行此操作,但是我可以为您提供有关如何执行此操作的想法。由于您的掩码包含同一位的许多重复,因此一种合适的方法是运行长度编码(RLE)。这个想法是,您可以对字节及其长度进行编码,而不是对单个字节进行编码:

aaabbbababaaaaaaaa -> 3a,3b,1a,1b,6a

有许多方法可以在实践中实现。我正在研究体素模型压缩,最适合我的方法是使用字节0x000xff作为转义序列。因此[0x00,N]编码N个零字节,[0xff,N]编码N个填充字节。其余字节保持未压缩状态。另外,您也可以只使用zlib进行DEFLATE压缩,我敢肯定也有GPU实现。

获得O(1)随机访问权限

任何类型的压缩技术都存在的问题是,它将数据缩减为可变大小,从而使得无法进行随机访问。为了解决这个问题,您必须将数据压缩为1024个字节。然后,您可以存储指向每个块开头的指针表,以允许您随机访问。

一个明显的问题是,一次只能压缩一个块,而每次访问一个不同的块时,也需要对其进行解压缩。这可能非常昂贵。

确定O(log n)随机访问

另一种技术是将数据压缩为八进制树。较高级别的字节的八位表示较低的八个字节中的哪个存在,哪些不存在。

      0       0         1      1        // Higher-level bitmask representing
     /        |         |       \       // which bytes exist.
0000.0000 0000.0000 0010.1111 1111.1111 // Lower-level bytes.

在这里,1代表现有子树,0代表丢失的子树。 我们可以将该树优化为:

      0       0         1      1
                        |       \
                     0010.1111 1111.1111

较高级别的零位表示较低级别的全零数据,因此我们可以优化那些较低级别的数据。通过将数据安排在这样的树中,我们可以以O(log n)复杂度随机访问任何位。这种技术的优点是我们有很多相邻的1或0,它们将被优化掉并在更高的级别上变成单个位。

请注意,我们还可以优化全一的子树。为此,我们在更高级别使用0x00的掩码。 0x00掩码自然不会出现,因为它会被优化为更高级别的单个零位。因此,我们可以为其赋予一些特殊含义。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...