【问题标题】:PHP Loop Performance OptimizationPHP 循环性能优化
【发布时间】:2010-12-27 11:50:50
【问题描述】:

我正在编写一个 PHP 函数,该函数需要遍历一个指针数组,并为每个项目拉入该数据(无论是来自 MySQL 数据库还是平面文件)。由于可能有成千上万的迭代,任何人有任何优化它的想法吗?

我的第一个想法是拥有一个缓存数据的静态数组,我可以进行任何修改,任何修改都会更改该缓存数组,然后最后我可以将它刷新到磁盘。但是,在超过 1000 个项目的循环中,如果我只在数组中保留大约 30 个,这将毫无用处。每个项目都不算大,但内存中的 1000 多个项目太多了,因此需要磁盘存储。

数据只是压缩后的序列化对象。目前我正在使用数据库来存储数据,但我想也许平面文件会更快(我不关心并发问题,我不需要解析它,只需解压缩和反序列化)。我已经有一个自定义迭代器,它将一次拉入 5 个项目(以减少数据库连接)并将它们存储在此缓存中。但同样,当我需要迭代数千个时使用 30 的缓存是相当无用的。

基本上我只需要一种方法来快速迭代这些项目。

【问题讨论】:

  • 我将尝试更清楚地解释自己...我正在编写一个神经元网络,所以我需要遍历一些神经元对象以影响它们的一些数据,然后保存它,进入下一个等等1000 多个神经元之后。然后我需要再次向后迭代(称为反向传播)。我认为最好的解决方案是在内存和 IO 访问之间找到一个媒介。如果我一次加载 100 个对象,这意味着更少的 IO 但更多的内存。

标签: php optimization neural-network concurrent-programming


【解决方案1】:

嗯,你还没有付出太多。你没有描述你的数据,你没有描述你的数据在做什么,或者你什么时候需要一个对象而不是另一个,以及这些对象是如何临时释放的,在什么情况下你需要它回来,以及.. .

所以任何人在这里说的任何话都将是在黑暗中的完整镜头。

...所以按照这些思路,这里是在黑暗中拍摄。

如果您在任何时候都只愿意在内存中保存 x 项,请为 x 项留出空间。然后,每次访问对象时,记下时间(这可能并不意味着时钟时间,而是可能意味着访问它们的顺序)。将每个项目保留在一个列表中(它可能不会在列表中实现,而是作为一个类似堆的结构),以便最近使用的项目更快地出现在列表中。当您需要将一个新项目放入内存时,您可以替换最长时间之前使用的项目,然后将该项目移到列表的前面。您可能需要保留项目的另一个索引,以便在需要时知道它们在列表中的确切位置。然后您要做的是查找项目所在的位置,根据需要链接其父指针和子指针,然后将其移动到列表的前面。可能还有其他方法可以优化查找时间。

这称为LRU 算法。这是虚拟内存的页面替换方案。它的作用是延迟你的瓶颈(磁盘 I/O),直到它可能无法避免。值得注意的是,这个算法并不能保证最优替换,但它的性能还是不错的。

除此之外,我建议您在很大程度上并行化您的代码(如果可能的话),以便在需要访问硬盘进行加载或转储时,您可以让该处理器忙于实际工作。

根据您的评论,您正在研究神经网络。在您最初输入数据的情况下(在校正阶段之前),或者当您积极使用它进行分类时,我不认为该算法是一个坏主意,除非没有可能的方法来适应内存中最常用的节点。

在校正阶段(也许是反向传播?),您必须在内存中保留哪些节点应该很明显......因为您已经访问过它们!

如果您的网络很大,那么您将无法在没有磁盘 I/O 的情况下侥幸成功。诀窍是找到一种方法来最小化它。 编辑>

【讨论】:

  • 是的,抱歉,这很难解释。数据是一个序列化的对象,所以当我反序列化它时,它将在内存中。这就是我目前正在做的事情。但是问题在于,当我需要重申所有内容时,缓存中的那些将是最后使用的,因此当另一个函数开始新的迭代时,直到最后都不需要缓存中的所有内容。作为记录,我正在研究神经元网络,因此这种精神错乱;)
  • 你是对的。问题是,对于训练。我必须使用一些输入向前运行网络,这意味着迭代一层中的神经元,然后遍历下一层中的神经元等等。然后通过计算最近运行的网络中的错误来向后运行它。我正在努力优化这一点,所以只发生一次迭代,但我认为这是不可能的。是的,无论哪种方式都需要磁盘 IO,但可能一次引入多个磁盘 IO 就是答案。毕竟内存很便宜。
【解决方案2】:

您可以在第一次读取对象时使用 memcached 存储对象,然后在后续调用中使用缓存版本。 Memcached 使用 RAM 来存储对象,所以只要你有足够的内存,你就会有很大的加速。 memcached有一个php api

【讨论】:

    【解决方案3】:

    您总是可以在获得所需数据后进行循环。这样它就不会继续循环。如果它是您存储的平面文件..您的服务器硬盘将遭受包含数千或数百万不同文件大小的文件。但是,如果您谈论的是存储在数据库中的整个实际文件。那么最好将它存储在一个文件夹中,然后将该文件的路径保存在数据库中。并尝试将拉取的项目放入 XML 中。这样它更容易访问,它可以包含许多属性,用于提取项目的详细信息,例如(名称、上传日期等)。

    【讨论】:

      【解决方案4】:

      显然,将其保存在内存中比其他任何方法都快。每个项目有多大?就算每个1K,一万也不过10M。

      【讨论】:

      • 如果它们是图像或类似的东西,您可能会看到几十兆或更多的数量级,具体取决于压缩级别。如果您在内存中有 100 个 15-meg 的图像对象,那么您只使用了 ~1.5 gig 的内存!
      • 每个项目可能在 1-5k 左右,但如果有 100 个并发用户,很快就会变高。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-01
      • 1970-01-01
      • 2020-07-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多