2009-12-17 122 views
2

我正在编写一个PHP函数,它需要遍历指针数组和每个项目,并将这些数据(来自MySQL数据库或平面文件)引入。任何人都可以有任何优化这个想法,因为有可能成千上万的迭代?PHP循环性能优化

我的第一个想法是我有一个缓存数据的静态数组,我的工作和任何修改将只是改变缓存的数组,然后在最后我可以刷新到磁盘。但是,如果我只在阵列中保留大约30个,则在超过1000个项目的循环中,这将毫无用处。每个项目不是太大,但是其中有1000多个内存太多,因此需要磁盘存储。

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

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

+0

我将尽力解释自己更清楚...我正在写一个神经元网络,所以我需要迭代一些神经元对象来影响他们的一些数据然后保存它,进入下一个等等等等1000+神经元。然后我需要再次迭代(称为反传播)。 我认为最好的解决方案是在内存和IO访问之间找到一个媒介。如果我一次加载100个对象,这意味着更少的IO但更多的内存。 – Louis 2009-12-17 02:33:08

回答

1

那么,你还没有完成很多工作。你没有描述你的数据,也没有描述你的数据在做什么,或者你需要一个对象而不是另一个对象,以及这些对象是如何暂时释放的,以及在什么情况下你需要它。

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

......所以沿着这些线条,这里是黑暗中的镜头。

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

这被称为LRU algroithm。这是虚拟内存的页面替换方案。它所做的是延迟瓶颈(磁盘I/O),直到它可能无法避免。值得注意的是,这种算法并不能保证最佳的替换,但它仍然表现很好。

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

<编辑> 根据您的评论,您正在研究神经网络。对于初始数据结果(在修正阶段之前)或者当您正在积极使用它进行分类时,我没有看到算法是一个坏主意,除非没有可行的方法来适应内存中最常用的节点。

在修正阶段(也许是后退?),应该明白你必须保留在内存中的节点......因为你已经访问过它们!

如果您的网络很大,那么您不会在没有磁盘I/O的情况下脱身。诀窍是找到一种方法来最小化它。 < /编辑>

+0

对不起,很难解释。数据是一个序列化的对象,所以当我反序列化它时,它会在内存中。这就是我目前所做的。但问题在于,当我需要重申所有事情时,缓存中的那些将是最后一次使用,因此当另一个函数开始新的迭代时,所有缓存中的内容都不需要直到结束。为了记录,我正在研究神经网络,因此这种疯狂;) – Louis 2009-12-17 01:51:40

+0

你是对的。问题在于训练。我必须用一些输入来运行网络,这意味着迭代一层中的神经元,然后是下一层中的神经元等。然后通过计算最近运行的网络中的错误来反向运行它。我努力优化这个,所以只有一个迭代发生,但我不认为这是可能的。是的,无论是哪种方式,磁盘IO都将需要,但可能一次带入很多是答案。内存毕竟是便宜的。 – Louis 2009-12-17 02:36:44

0

显然,将它保存在内存中比其他任何东西都快。每件物品有多大?即使它们每个都是1K,其中一万个也只有10M。

+0

如果它们是图像或类似的东西,你可以看到几十meg或更多的订单,具体取决于压缩级别。如果你在内存中有100个15兆像素的图像对象,那么你只需要使用~1.5G内存! – 2009-12-17 01:44:38

+0

每个项目大概在1-5k左右,但后来说有100个并发用户,这很快就会变得很高。 – Louis 2009-12-17 01:55:54

0

在获得所需的数据后,您总是可以循环展开。所以它不会继续循环。如果它是一个平面文件,您正在存储..您的服务器硬盘将受到包含数千或数百万个不同文件大小的文件。但是如果你正在谈论存储在数据库中的整个实际文件。那么将它存储在一个文件夹中并将该文件的路径保存在数据库中会更好。并尝试将拉出的项目放入XML中。因此访问起来更容易,并且可以包含很多属性,例如(姓名,上传日期等)。

0

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