2010-08-03 51 views
0

我的程序正在經歷一個令人討厭的性能下降。它基本上是一對嵌套for循環,它執行一對數據集的操作,然後寫入結果。問題在於,300,000對中的約500對在0.07秒/對到5秒/對之間變慢,並且CPU使用率從接近100%下降到〜4%。所有使用的內存都在嵌套循環之前分配,並在循環之後釋放。與C程序劇烈CPU下降

這裏是僞代碼,這樣你就可以有希望的想法:

for (i=0; i<759; i++) { 
    read_binary_data(data_file_1, data_1); 
    read_binary_header(header_file_1, header_1); 
    for (j=i+1; j<760;j++) { 
     read_binary_data(data_file_2, data_2); 
     read_binary_header(header_file_2, header_2); 

     do_operation(data_1, data_2, out_data); 
     update_header_data(header_1, header_2, out_header); 

     write_binary_data_and_header(out_data, out_header); 
    } 
} 

我已經把時序標誌的開頭和第二個for循環看到上面引述的時機結束,但我想知道如果可能有更好的調試選項來顯示操作速度減慢的原因。到目前爲止我唯一的想法是文件系統阻塞,但是我只在每次運行時打開5-6個文件,每個文件在其子程序結束時都關閉。

下午10點15分更新太平洋時間:
經過各種測試,我發現罪魁禍首似乎是在read_binary_data部分。許多文件可能需要3秒以上。我將嘗試將所有二進制數據打包到一個文件中並一次讀取,因此我只需要讀取一個。我敢打賭我會用完內存,但它值得一試,如果發生這種情況,我就不那麼雄心勃勃,並且嘗試每次少於760 * 2 * 31 * 43201浮點數組我想這應該在16 GB左右?)。

+0

「但我只在每次運行時打開5-6個文件,每個文件在子程序結束時都關閉」 - 這怎麼證明它不是文件系統阻塞? – nos 2010-08-03 21:45:14

+0

我想它並不能證明它,但我認爲我嘗試打開文件的次數越少,阻止文件系統的可能性就越小。 – robporritt 2010-08-03 21:48:54

回答

5

你是否釋放了你持有數據的緩衝區?這聽起來像是你已經耗盡內存,並在500個文件後切換到交換。你的內存使用情況如何?

+0

我沒有釋放任何緩衝區,我只是重複使用相同的內存位置並覆蓋不再需要的內容。 Top通常顯示內存低於1%(最大內存使用量在data_1和data_2中,這是浮點數組,在磁盤上大約爲20mb) – robporritt 2010-08-03 21:41:40

+1

您的文件有多大?如果你註釋掉do_operation()和write()以便你正在讀的所有內容會發生什麼呢?同樣,如果你註釋掉read_data()和do_operation,以至於你只是寫了什麼呢?你的機器有多少內存? – Amoss 2010-08-03 23:38:29

+0

這些文件都是2 * 31 * 43201浮點陣列,我相信它是一個帶有6GB內存的i7。 do_operation()實際上只是main中的一個長序列的簡寫(壞 - 我知道)。快速評論閱讀和快速閱讀。 – robporritt 2010-08-04 05:13:12

2

涌現在腦海,儘管你的要求是內存不被分配循環中的第一件事情,是

  • 內存泄漏
  • 內存碎片
  • 緩存飽和

沒有關於實際情況的更多細節,比如你正在運行的環境或者你的函數正在調用的其他函數,那麼真的不可能推測更多。問題太抽象了。

3

也許你對文件的寫作效率低下,隨着你的進步,你需要做更多的尋找?

也許會將寫入磁盤的兩行註釋掉,看看是否得到一致的運行。

否則,它可能是您的閱讀。很難看到你是如何實際完成文件操作的,但很容易以非常昂貴的方式來完成。

無論哪種方式,如果你的CPU是低,你的內存不足,請您留下了阻塞I/O操作!

0

除非您分配太多內存以致系統開始交換,否則您是I/O綁定的。

2

首先到您的實際問題 - 「C」沒有調試選項來處理I/O性能或任何其他類型的性能。你的IDE,調試器或操作系統可能,但我恐怕不知道任何細節。

愚蠢的問題 - 所有的循環產生相同數量的輸出嗎?也許前500名是小的。

可能是500循環是填充磁盤寫入緩存需要多長時間(在一個或多個級別 - 進程,操作系統,硬件),並且在此之後程序是I/O綁定的。在不知道涉及的數據量的情況下,無法確定是否可能。

嘗試將1GB的數據寫入文件並計算時間,以瞭解持續率是否合理。如果每對0.07秒,乘以每對數據量,計算出的速度比這個速率更快,那麼你的初始快速速率是一次性的特別優惠:磁盤遲早要趕上。

除此之外,更多地考慮你的輸出是什麼,你沒有詳細說明。用直線書寫?來回尋找?將記錄插入到磁盤上的有序數組中,以便每個寫入必須平均移動目前寫入數據的50%?隨着時間的推移,不同的訪問模式顯然會有很大差異。

我假定讀取緩存是無用的,所以您的讀取速度將始終相當一致,所以我專注於輸出而不是輸入。事實並非如此,但如果電腦無法預測您的訪問模式,那麼這是一個相當不錯的近似值。

即使如此,300000 * 5秒超過400小時。這是足夠的時間讓任何一臺致命的計算機多次寫入整個硬盤。所以你必須做一些非常奇怪的事情,因爲原始寫入速度是全部存在的。

+0

所有循環產生相同的輸出並覆蓋相同的數組。輸出是一個直線寫 - 開二進制文件,輸出一個結構,然後將浮點數組寫入一個文件中,關閉二進制文件。它在閱讀中顯得很慢。 – robporritt 2010-08-04 05:14:50

0

你正在做一個線性搜索類的東西。你的數據存儲在一個文件中?

如果是,那麼您可以一次只讀取所有數據,然後將其存儲在二進制搜索樹中。它會減少程序的時間複雜度。