gpt4 book ai didi

c - c - 如何在c中比fprintf更快地写入文本文件?

转载 作者:行者123 更新时间:2023-12-04 10:47:56 24 4
gpt4 key购买 nike

我必须将一些图形数据(结构数组)保存到文本文件中。我使用 fprintf 制作了工作程序,但为了获得额外的积分,我需要更快。我花了几个小时在谷歌上搜索是否有更快的东西并尝试使用 fwrite (但我无法将 fwrite 作为文本)我真的找不到任何其他功能等。

这是我使用 fprintf 的写函数:

void save_txt(const graph_t * const graph, const char *fname)
{
int count = graph->num_edges, i = 0;
FILE *f = fopen(fname, "w");
while (count > 0) {
int r = fprintf(f, "%d %d %d\n", (graph->edges[i].from), (graph->edges[i].to), (graph->edges[i].cost));
i++;
if (r >= 6) {
count -= 1;
} else {
break;
}
}
if (f) {
fclose(f);
}
}

最佳答案

我会尝试在流上设置写入缓冲区,并尝试使用不同大小的缓冲区(例如 1K、2K、4K、8K 等)。请注意,默认情况下,您的文件已经在使用 BUFSIZ 值的缓冲区,这可能已经足够了。

#define BUFFERSIZE 0x1000

void save_txt(const graph_t * const graph, const char *fname)
{
int count = graph->num_edges, i = 0;
unsigned char buf[BUFFERSIZE];

FILE *f = fopen(fname, "w");
setvbuf(f, buf, _IOFBF, BUFFERSIZE);

...

输出文件 f带有默认的 BUFSIZ 缓存,因此它可能会受益于更大的全缓冲写入缓存。

当然,这假设您正在写入相对较慢的介质,并且节省的时间是相关的;否则,无论是什么让你慢下来 不在这里 ,因此提高保存性能不会对您有明显帮助。

有像 prof 这样的工具和 gprof这可以帮助您确定您的程序花费最多时间的地方。

一种更尴尬的可能性是将 Kiwi 的答案与缓冲写入调用合并,以避免 printf 中验证使用哪种格式的代码,因为您已经知道这一点,并尽可能少地使用 I/O 调用(即使只有一个如果 BUFFERSIZE 大于目标文件的长度)。
// These variables must now be global, declared outside save_txt.
char kiwiBuf[BUFFERSIZE];
size_t kiwiPtr = 0;
FILE *f;

void my_putchar(char c) {
kiwiBuf[kiwiPtr++] = c;
// Is the buffer full?
if (kiwiPtr == BUFFERSIZE) {
// Yes, empty the buffer into the file.
flushBuffer();
}
}

void flushBuffer() {
if (kiwiPtr) {
fwrite(kiwiBuf, kiwiPtr, 1, f);
kiwiPtr = 0;
}
}

您现在需要在关闭之前刷新缓冲区:
void save_txt(const graph_t * const graph, const char *fname)
{
int i, count = graph->num_edges;
f = fopen(fname, "w");
if (NULL == f) {
fprintf(stderr, "Error opening %s\n", fname);
exit(-1);
}
for (i = 0; i < count; i++) {
my_put_nbr(graph->edges[i].from);
my_putchar(' ');
my_put_nbr(graph->edges[i].to);
my_putchar(' ');
my_put_nbr(graph->edges[i].cost);
my_putchar('\n');
}
flushBuffer();
fclose(f);
}

更新

通过声明 my_putchar功能为 inline并且使用 4K 缓冲区时,上述代码(使用从随机整数数组中读取图形的模拟进行修改)比 fprintf 快 6 倍左右。在
Linux mintaka 4.12.8-1-default #1 SMP PREEMPT Thu Aug 17 05:30:12 UTC 2017 (4d7933a) x86_64 x86_64 x86_64 GNU/Linux
gcc version 7.1.1 20170629 [gcc-7-branch revision 249772] (SUSE Linux)

其中大约 2 倍似乎来自缓冲。 Andrew Henle 让我注意到我的代码中有一个错误:我将结果与无缓冲输出的基线进行比较,但是 fopen默认情况下使用 BUFSIZ 值,在我的系统上 BUFSIZ 是 8192。所以基本上我已经“发现”了:
  • 8K缓冲区没有优势,4K就够了
  • 我最初使用 _IOFBF 的建议是 一文不值因为系统已经为你做了。这反过来意味着 Kiwi的回答最正确 ,因为 - 正如安德鲁指出的那样 - 避免了 printf的检查和转换。

  • 此外,总体增加(谷歌阿姆达尔定律)取决于节省处理时间的比例。显然,如果一小时的精心制作需要一秒钟的节省,那么节省速度加倍,您就可以节省半秒钟;同时将细化速度提高 1% 可为您节省 36 秒,或 72 倍。

    我自己的示例代码被设计为完全面向保存的非常大的图;在这种情况下,写入速度的任何微小改进都可能获得巨大的返回,这在现实世界中可能是不切实际的。

    另外(在回答评论时),虽然使用足够小的缓冲区会减慢保存速度,但完全不确定使用更大的缓冲区是否会受益。假设整个图总共生成 1.2Kb 的输出;那么当然任何超过 1.2Kb 的缓冲区值都不会产生任何改进。实际上,分配更多内存可能会对性能产生负面影响。

    关于c - c - 如何在c中比fprintf更快地写入文本文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47952423/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com