扫描位数组以查找多个位的模式
Scanning bit array for pattern of multiple bits
我正在编写一个由位图(uint8_t
数组)支持的内存分配器,当前当分配请求出现时,我扫描从 0 到 n 位的位图顺序并搜索可以满足请求的空间。(位 1 表示页面使用 0 表示页面是免费的)现在,与其一次搜索一位空间,不如有技术可以更快地扫描整个阵列?即,如果收到对 3 页内存的请求,我想一次性搜索数组中的000
模式,理想情况下无需循环?
PS:我没有使用std::bitset
因为它不适用于我正在使用的编译器。AFAIK 也不允许我搜索多个位。
编辑:位被打包成一个字节,uint8_t
有8页(每比特1个)编码。
要扫描一个空白页,您可以一次循环一个完整的字节遍历位数组,并检查它是否小于 255。如果它较小,则至少有一个零位。更好的方法是一次扫描 32 或 64 位(无符号整数),然后在 uint 内缩小搜索范围。
为了优化一点,您可以跟踪具有零位的第一个字节(并在释放页面时更新该位置)。一旦您分配了该免费页面,这可能会产生误报,但至少下次扫描可以从那里开始而不是从头开始。
如果您愿意以 2 的幂对齐较大的块(具体取决于您的数据结构),则可以优化对多个页面的扫描。例如,要分配 8 页,您只需扫描一个完整的字节为零:
1 page: scan for any zero bit (up to 64 bits at a time)
2 pages: scan for 2 zero bits at bit position 0,2,4,6
3-4 pages: scan for zero nibble (for 3 pages, the fourth would be available for 1 page then)
5-8 pages: scan for an empty byte
for each of the above, you could first scan 64 bits at a time.
这样,您就不必担心(或检查)byte/uint32/uint64 边界处的重叠零范围。
对于每种类型,可以保留/更新具有第一个空闲块的起始位置。
不是您问题的完整答案(我想),但我希望以下函数可以提供帮助。
template <typename I>
bool scan_n_zeros (I iVal, std::size_t num)
{
while ( --num )
iVal |= ((iVal << 1) | I{1});
return iVal != I(-1);
}
它返回(如果我写得正确)true
如果(不是在哪里)iVal
中至少有num
个连续的零位.
以下是T
uint8_t
时的完整工作示例
#include <iostream>
template <typename I>
bool scan_n_zeros (I iVal, std::size_t num)
{
while ( --num )
iVal |= ((iVal << 1) | I{1});
return iVal != I(-1);
}
int main()
{
uint8_t u0 { 0b00100100 };
uint8_t u1 { 0b00001111 };
uint8_t u2 { 0b10000111 };
uint8_t u3 { 0b11000011 };
uint8_t u4 { 0b11100001 };
uint8_t u5 { 0b11110000 };
std::cout << scan_n_zeros(u0, 2U) << std::endl; // print 1
std::cout << scan_n_zeros(u0, 3U) << std::endl; // print 0
std::cout << scan_n_zeros(u1, 4U) << std::endl; // print 1
std::cout << scan_n_zeros(u1, 5U) << std::endl; // print 0
std::cout << scan_n_zeros(u2, 4U) << std::endl; // print 1
std::cout << scan_n_zeros(u2, 5U) << std::endl; // print 0
std::cout << scan_n_zeros(u3, 4U) << std::endl; // print 1
std::cout << scan_n_zeros(u3, 5U) << std::endl; // print 0
std::cout << scan_n_zeros(u4, 4U) << std::endl; // print 1
std::cout << scan_n_zeros(u4, 5U) << std::endl; // print 0
std::cout << scan_n_zeros(u5, 4U) << std::endl; // print 1
std::cout << scan_n_zeros(u5, 5U) << std::endl; // print 0
}
相关文章:
- 在C++的一系列数字中查找重复模式
- C++ 使用存储在动态数组中的文本文件中的数据查找模式
- 在数组中查找重复模式
- 在图像中查找相似的(大)模式
- 在C++中查找文本中的模式
- 扫描位数组以查找多个位的模式
- 在数组中查找模式的最有效方法?
- 为什么 POSIX 允许在现有文件末尾 (fseek) 之外查找只读模式
- 编写模式识别'函数以查找特定顺序出现的数字?C++
- 查找模式C++
- 从列表到数组C 查找模式或最常见的数字
- 使用双阵列查找模式
- 查找整数中的重复模式
- 查找未排序数组的模式,以及该数组是否具有多个模式或无模式
- 如何通过将数组的指针传递给函数来查找数组的模式?C++
- 使用 bin 搜索查找排序数组的模式
- 在数组中查找一个或多个模式
- 如何在虚幻编辑器内容浏览器中查找虚幻游戏模式
- 在字典中查找单词模式,高性能
- 在 windbg 中的用户模式转储中查找 hwnd 信息