2009-12-17 111 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