小编Gor*_*yle的帖子

C语言中大型磁盘文件的二进制搜索

这个问题经常在StackOverflow上重复出现,但我已经阅读了所有以前的相关答案,并对问题略有不同.

我有一个包含4.75亿行相同大小的23Gb文件,每行包含一个40个字符的哈希码,后跟一个标识符(一个整数).

我有一个传入的哈希码流 - 总共有数十亿个 - 对于每个传入的哈希码,我需要找到它并打印出相应的标识符.这项工作虽然很大,但只需要完成一次.

该文件太大,我无法读入内存,因此我一直尝试以下列方式使用map:

codes = (char *) mmap(0,statbuf.st_size,PROT_READ,MAP_SHARED,codefile,0); 
Run Code Online (Sandbox Code Playgroud)

然后我只是根据代码中的地址使用地址算法进行二进制搜索.

这似乎开始工作得很漂亮,并在几秒内产生几百万个标识符,使用100%的cpu,但是经过一些看似随机的时间,它会减慢到爬行的速度.当我使用ps查看进程时,它已使用100%的cpu从状态"R"更改为使用1%cpu的状态"D"(磁盘绑定).

这是不可重复的 - 我可以在相同的数据上再次启动该过程,并且可能在"慢速爬行"发生之前运行5秒或10秒.昨晚一次,在此之前我差不多花了一分钟.

一切都是只读的,我没有尝试任何写入文件,我已经停止了机器上的所有其他进程(我控制).它是一台现代的Red Hat Enterprise Linux 64位机器.

有谁知道为什么这个过程变得磁盘受限以及如何阻止它?

更新:

感谢大家的回答,以及您的想法; 之前我没有尝试过所有各种改进,因为我想知道我是否以某种方式错误地使用了mmap.但答案的要点似乎是,除非我能将所有东西都挤进记忆中,否则我将不可避免地遇到问题.所以我将哈希码的大小压缩到没有创建任何重复项的前导前缀的大小 - 前15个字符就足够了.然后我将生成的文件拉入内存,并分别运行大约20亿个传入的哈希码.

c linux binary-search

6
推荐指数
1
解决办法
1524
查看次数

双向 popen() 在 C 中的 Mac OS X 上工作吗?

我的问题 我 在哪里可以找到一个清晰的 C 代码工作示例,该示例在 MacOS 上设置和使用带有 popen() 的双向管道?

我正在尝试使用 popen() 在我的 C 程序和 Mac OS X 上的外部程序之间打开一个双向管道。

我的 C 程序必须反复:

  • 从它自己的标准输入读取输入行
  • 将其重新格式化为外部程序的输入
  • 调用外部程序,将格式化的输入传递给外部程序的标准输入
  • 从外部程序的标准输出读取结果
  • 处理这些结果并在它自己的标准输出上产生一些诊断输出

如果我使用实际文件来存储输入/输出然后使用 system() 或类似文件,我可以轻松地做到这一点,但这太慢了,因为我有数十亿个输入。所以我想完全在内存中完成。

相关的手册页,以及本组和其他人的互联网讨论表明,我可以打开一个通向外部程序的管道,然后像写入文件一样使用 fprintf 写入它。

pout = popen(external_program, "w")
fprintf(pout,input_to_external_program);
Run Code Online (Sandbox Code Playgroud)

这作为一个单向管道工作正常,将格式化的输入输入到外部程序中。

显然,在 Mac OS 上可以通过指定“r+”而不是“r”或“w”作为 popen 的相关参数来打开双向管道,从而使用相同的管道读取和写入程序。

pout = popen(external_program, "r+")
fprintf(pout,"%s", input_to_external_program);
fscanf(fpout,"%s", &output_from_external_program);
Run Code Online (Sandbox Code Playgroud)

我不需要在读、写、读、写等之间交替,因为所有需要发生的是我的程序将在开始读取外部程序的输出之前完成将输入写入外部程序。

外部程序应该只读取一个自包含的输入序列(即它以一个特殊的行结束以指示“输入结束”),然后运行到完成,写入输出,然后终止。

但是当我尝试使用此功能时,它不起作用,因为有些东西阻塞了 - 外部程序启动,但甚至没有完成一个输入。

即使我只是忘记做任何阅读,而只是将“w”替换为“r+”,那么以前工作的功能也会停止工作。

今天早上的大部分时间我都在寻找一个可以修改的工作 popen() 示例,但我发现的所有内容都只使用了单向管道。

所以我们最终回到

我的问题*我在哪里可以找到一个清晰的 C 代码工作示例,该示例在 MacOS 上设置和使用带有 popen() 的双向管道?**

如果它更容易,我也许可以用 Perl 替换 C 部分。

更新

感谢您的回答,但我仍然无法使其正常工作,尽管我可以制作一些小规模版本。例如,我编写了一个小程序,它会向输入的任何数字添加一个,如果输入为 -99 …

c pipe popen

5
推荐指数
1
解决办法
920
查看次数

标签 统计

c ×2

binary-search ×1

linux ×1

pipe ×1

popen ×1