c - C - 对具有可变长度元素的大型二进制文件进行排序
问题描述
我的问题如下:
- 我有一组长度可变的元素存储在我们将调用的二进制文件中
data.bin
。 - 每个元素都有一个我们将调用的排序键参数
key
、一个大小size
和一个 data.bin 中的文件位置pos
。这 3 个参数表示为一个结构。
问题是如何data.bin
有效地排序。
现在我已经定义了一个数据结构
typedef struct {
int key;
unsigned int size;
long int pos;
} index
和一个数组index indices[]
,其中包含存储在 中的元素的值data.bin
。该列表根据key
使用快速排序算法连续排序,即使对于非常大量的条目(例如10M)也足够快。然后我使用排序列表indices
将排序后的data.bin
文件写为sorted.bin
. 我的代码的核心如下(这里我故意删除了错误检查部分):
size_t mergeBuffIdx = 0;
char *mergeBuff = (char *) calloc(MERGE_BUFF_SIZE, sizeof(char));
for (unsigned int idx = 0; idx < numEntries; idx++) {
unsigned int dataSize = indices[idx].size;
if ((mergeBuffIdx + dataSize) >= MERGE_BUFF_SIZE) {
fwrite(mergeBuff, sizeof(unsigned char), mergeBuffIdx, sortedDataFile);
mergeBuffIdx = 0;
}
// set the file pointer at the beginning of the data file position
fseek(dataFile, indices[idx].pos, SEEK_SET);
// read the data from the file as an unsigned char array
fread(&mergeBuff[mergeBuffIdx], sizeof(unsigned char), dataSize, dataFile);
mergeBuffIdx += dataSize;
}
// write remaining data
if (mergeBuffIdx != 0) {
fwrite(mergeBuff, sizeof(unsigned char), mergeBuffIdx, sortedDataFile);
}
这种方法非常简单,但在data.bin
非常大(我的一般用例是 30GB)时很快就会变得非常慢,条目数约为 10M 并且两个连续排序的条目可能在原始data.bin
文件上很远。对于data.bin
1GB 的文件,即使我使用的是 SSD HD,这种方法也可能需要 30 多分钟。
您对这个问题有一些想法、替代解决方案或方法吗?
我曾尝试使用性能相似甚至最差的内存映射文件。我的想法是瓶颈是fseek
调用,但是,我无法找出替代方案和更高效的方法。
感谢阅读,S,
解决方案
使用您的方法,每次读取只能获得一个元素,因此根据排序键读取文件的命令为 1000 万条。至少 SSD 将消除随机访问开销。
使用外部合并排序直接对数据进行排序而不是排序键并进行随机访问应该更快。这将允许一次使用可能超过 256 MB 的读/写。初始通道将读取 256MB 块,对元素进行排序,然后写入 256MB 块(其中 128 个是 32GB)。16 路合并(2048 次读取,每次 16 MB)然后是 8 路合并(1024 次读取,每次读取 32 MB)将排序大约 32GB 的数据。对于 16 或 8 路合并,您可能希望使用某种形式的优先级队列,例如堆。
您没有提及密钥/大小信息是否在单独的文件中。如果有足够的空闲内存,您可以在外部合并排序期间将此信息保留在内存中,并在完成后将其写回。
推荐阅读
- c++ - 我想使用 dev c++ 从 file.txt 打印出结构变量,但屏幕为空白且没有错误
- python - Pandas - 根据列值删除整行的有效方法
- spring-cloud-stream - Spring Cloud Data Flow Aggregator 处理器不会启动
- windows - 为什么未检测到我的 Move-Item 命令过滤?
- woocommerce - 在 woocommerce 结帐时根据国家/地区删除验证特定字段
- wordpress - URL 预览未在 wordpress 中显示
- sql - SQL 语句不按升序排列名称
- python - 返回“无”的递归函数
- css - 具有独特元素的 Elementor 中继器
- ios - 小部件扩展在 Deivce 或模拟器中不出现且 Swift UI 预览失败