【问题标题】:C - Dynamic ArrayC - 动态数组
【发布时间】:2011-10-08 17:31:14
【问题描述】:

我正在尝试使用 fscanf() 提供一个数组,同时循环一个包含整数列表的文件,n 个整数长。看来我需要使用 malloc 和/或可能的 realloc。我听说 malloc 命令需要大量的执行时间,并且最好过度分配。有人介意帮助我了解实现这一目标的组成部分吗?

免责声明:我是 C 新手。

【问题讨论】:

  • I've heard。我认为您需要花时间阅读一些有关动态分配的信息。那里有一堆教程。不要害怕。
  • 声明:你不会注意到malloc()的执行时间。

标签: c arrays dynamic malloc realloc


【解决方案1】:

不,您所听到的具有误导性(至少对我而言)。 malloc 只是一个函数,而且通常很快。

  • 大部分时间它在用户空间完成所有工作。它“过度分配”,所以你不必
  • 由于几乎每个人都使用malloc,因此簿记(带有空闲块等的链表)已经过高度优化

认为你可以在这场比赛中轻松击败malloc 是不现实的。很抱歉,如果这不能回答您的问题(这很笼统),但您必须意识到没有 (spoon) 可以轻松实现的优化。

【讨论】:

  • malloc is a just a function,嗯,它是最重要的功能之一,所以我不会说它是just 一个功能。 :)
  • @Als 我听到了 :-) 我的意思是“不是系统调用”。
  • 不同意。 Malloc,取决于它的实现方式,通常不是一个快速的函数。很多时候,它是性能排名前十的猪,具体取决于您跟踪的块数。这完全取决于内部块列表的处理方式,尽管添加或删除项目通常是 O(n) 或更糟的执行时间。如果 OP 在 while 循环中执行 malloc,他很有可能会感觉到开销,但在与 fscanf 等 IO 函数结合时不会。
  • @Michael Dorgan 您可能是对的,但是为找出所需大小而进行的工作的成本可能会令人望而却步。现在,如果他说他想realloc,那是另一个问题。
  • realloc - 啊!由于我们继承的库非常差,前几天我不得不在嵌入式设备上实现它。该功能是管理内存的一种丑陋方式。碎片化 - 检查。内存不断移动 - 检查。容易出错 - 检查。坏事的三重奏。
【解决方案2】:

读取文件会比分配内存慢很多!

您可能想要阅读整个文件并找出您想要的整体数量,然后一次性使用 malloc()。

malloc(sizeof(int)*n)

【讨论】:

  • 这是处理内存分配的更好方法。如果您可以在读取之前获得一个 filesize() 来预先分配整个缓冲区,那就更好了。
  • 这是一个很棒的建议。谢谢。
  • 所以...建议是文件被读取两次?一次找出它是多长时间,然后再次存储它?如果性能不是主要问题,那是有道理的。
【解决方案3】:

过早的优化是万恶之源(google it)。

也就是说,为手头的任务分配您认为合理/典型的任何数量,并在您必须重新分配时将其加倍。这种策略很难被击败。

【讨论】:

    【解决方案4】:

    对于您的具体情况,malloc 不会给您带来问题。 fscanf 的运行时间将比 malloc 和 free 的开销慢很多很多倍。但是,它可以添加到应用程序的高性能区域。在这些领域,还有其他方法,例如内存池和固定大小的分配器,可以对抗 malloc() 的开销。但是,当您刚开始时,您完全不需要担心性能开销。

    【讨论】:

      【解决方案5】:

      请注意,malloc() 为每个分配增加了一些开销以维护其内部数据结构(在常见实现中至少为 4 个字节),因此如果整数长度为 4 个字节,则为每个整数执行 malloc() 将具有 > = 50% 的开销(可能是 75%)。这相当于在 Java 中使用 Integer 的数组,而不是 int 的数组。

      正如@Charles Dowd 所说,一次性分配所有内存要好得多,以避免开销。

      【讨论】:

      • 更不用说对可能非常大的文件中的每个整数执行函数调用可能有点慢。
      【解决方案6】:

      您肯定不想在读取每个整数时都调用mallocrealloc,这是肯定的。你能估计一下你需要多少空间吗?你控制文件格式吗?如果是这样,您可以让文件的第一行是一个整数,表示要从文件中读取多少个整数。然后,您可以一次性分配所需的所有空间。如果您不控制格式并且无法执行此操作,请遵循此线程中提到的其他建议:分配一个合理大小的缓冲区,并在每次空间不足时将其加倍。

      【讨论】:

        【解决方案7】:

        这是一个文本文件(不是二进制文件),不是固定格式,对吧?否则很容易从文件大小(buffer_size = file_size / record_size,buffersize 以字(int 的大小),其他大小以字节为单位)计算数组的大小。

        这就是我会做的(但在应用统计方面我有点发疯)。

        1) 一个数字(又名记录)将在文件中占用的最大字符数(又名字节)是多少,不要忘记包括行尾字符(CR、NF)和其他空白字形(空格、制表符等)?如果您已经可以估计记录的平均大小,那么使用它而不是最大大小会更好。

        initial_buffer_size = file_size / max_record_size + 1    (/ is integer division)
        

        2) 分配该缓冲区,将整数读入该缓冲区,直到它已满。如果读取了整个文件,那么您就完成了,否则调整缓冲区大小或重新分配缓冲区以满足您新的估计需求。

        resize_size = 
           prev_buffer_size
           + bytes_not_read / ( bytes_already_read / number_of_records_already_read ) 
           + 1
        

        3) 读入该缓冲区(从上次读取结束的地方)直到它已满,或者所有文件都已被读取。

        4) 如果未完成,请使用新的prev_buffer_size 从步骤 2) 重复。

        如果从字节大小的角度来看,数字(记录)是完全随机分布的,这将最有效。如果没有,并且你知道它们有什么样的分布,你可以据此调整算法。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-01-18
          • 1970-01-01
          • 2013-07-20
          • 2018-07-29
          • 1970-01-01
          • 2011-02-09
          相关资源
          最近更新 更多