【问题标题】:Fill a vector of uint16_t using a boost::dynamic_bitset<>使用 boost::dynamic_bitset<> 填充 uint16_t 的向量
【发布时间】:2018-12-03 07:01:03
【问题描述】:

我正在创建一个使用 Huffman 压缩来压缩文件的程序。最初我使用 uint8_t 的向量来存储文件中的字节,但性能很糟糕(解压缩 74 MB 文件需要 2 小时)。 我决定使用 16 位块来表示文件中的值。

最初,我有这个(输入位集有 5.2 亿位)

std::vector<uint8_t> bytes;
boost::dynamic_bitset<unsigned char> input;

boost::to_block_range(input, std::back_inserter(bytes));

这很好用,它填充了一个充满 8 位整数的向量,代表文件的每个字节。每个位的频率都记录在一个大小为 256 的整数向量中。这运行得非常糟糕。解码一个字符串绝对需要永远,因为我的文件中这些整数的频率是巨大的。我认为如果我使用 16 位整数并将频率存储在大小为 65536 的向量中会更好。这是我填充“字节”向量的尝试:

std::vector<uint16_t> bytes;
boost::dynamic_bitset<unsigned char> input;

boost::to_block_range(input, std::back_inserter(bytes));

这里的问题是 to_block_range() 函数从我的位集中取出 8 位并用 8 个零填充它们,而不是一次取出 16 个字节。

有没有办法以这种方式从动态位集中填充 uint16_t 的向量?

【问题讨论】:

  • 您是否对代码进行了分析以检查性能问题出在哪里?
  • 是的。它发生在每个字节的每个位表示都附加到字符串之后。这个字符串代表了bitset的压缩版本,但是由于只有256个可能的唯一值,这些值的频率是巨大的,这导致字符串是巨大的。要使用霍夫曼解码来解码这个字符串,必须逐个字符地读取它,这需要几个小时
  • huff 解码应该是一个简单而快速的过程,你能更详细地解释一下你在做什么吗?我不明白为什么你的数字频率很大会导致问题。我也不确定我是否理解这里 bitset 的使用,也许你使用了错误的工具来完成这项工作?
  • 道歉。我有大量的位集要压缩。我正在将 8 位块读入一个整数(uint8_t)并将所有这些存储在一个向量中。在读入这些内容时,我会增加一个大小为 256 的数组的相应索引(例如,如果我读入 00001010,则索引 10 将增加)。然后,每个字节(共 256 个)都有自己唯一的识别码。更频繁出现的字节获得较短的代码,不太频繁出现的字节获得较长的代码。然后,我通读向量中的每个字节,并将其对应的前缀代码附加到一个字符串中。完成后,该字符串
  • 将代表文件的压缩版本。为了解压缩,我必须读取该压缩字符串的每个字符并使用它遍历树以提取原始(解压缩)值。我的问题是,使用 8 位整数意味着对于像我这样大小为 5 亿的位集,0-256 中的每一个数字都会出现成千上万次,从而产生一个巨大的压缩字符串。如果我可以读取 16 个块的位集,我可以有 65536 个不同的值,这意味着我的频率会低得多,压缩的字符串会更小

标签: c++ boost-dynamic-bitset


【解决方案1】:

这里的问题可能不是你想的那样。

在您的基于字节的方法中,添加 reserve 调用可能会大大改善情况。

std::vector<uint8_t> bytes;
boost::dynamic_bitset<unsigned char> input;

bytes.reserve(input.num_blocks());
boost::to_block_range(input, std::back_inserter(bytes));

仅插入到向量后面的问题是向量在增长时会被复制多次。你可以通过给它足够的内存来避免这种情况。

【讨论】:

  • to_block_range 实际上运行得相当快。这大约需要 30 秒,我相信这会加快速度,但我的问题是我必须创建一个唯一的二进制字符串来表示每个字节。然后,这些代码中的每一个都被连接到一个表示压缩版本的字符串上。由于我只有 256 个可以表示的数字,所以这些数字的频率是巨大的,而压缩字符串也是如此。如果我可以表示 16 位数字而不是 8 位数字,我将有 65536 个数字得到一个代码,所以频率会急剧下降
  • 基本上我需要将每个块的位数从 8 更改为 16。
  • @ConnorS 我建议您尝试保留空间,如果您需要 30 秒运行,这会快很多。
  • @ConnorS 您是否有理由不使用 dynamic_bitset&lt;uint16_t&gt;vector&lt;uint16_t&gt; 一起使用,所以副本有效?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-17
  • 2018-02-05
相关资源
最近更新 更多