1. 程式人生 > 程式設計 >總結一次C++ 程式優化歷程

總結一次C++ 程式優化歷程

近期用到了一位師兄寫的C++程式,總體功能良好。使用不同的資料測試,發現了一個明顯的缺點:大資料量下,預處理過程耗時很長。中科院的某計算叢集,普通佇列中的程式執行時間不能超過6個小時。而手上這套程式,大資料量下預處理就花了不止六個小時,結果當然是還沒開始就被結束了。

和天河二號的工作人員聯絡,確認沒有執行時間限制。於是開通了天河二號的賬號,把程式扔上去跑。執行大資料量時,程式莫名被kill。詢問技術支援,得知是記憶體耗盡,建議每個節點的程序數少一點。如此折騰了兩次,大資料量的例子沒跑通,大部分時間都費在預處理上,然後程式崩了,又要調整引數重新再來。

耗時長,最多是多花點機時,問題不大。但是沒跑通的情況下每次要等五六個小時,然後才知道能否執行,測試然後反饋的過程太低效。忍無可忍,就開始進行優化吧!

第一步,找出耗時的點。原來的程式輸出日誌用的cout,沒有附帶時間,不能通過日誌發現耗時的點。為了找出效能關鍵點,第一步是改進log,在輸出中加上時間。寫了一個Log類,替換掉cout,程式的輸出中就帶上時間了:

#include "../include/Log.hpp"

#include 
#include 
#include 
#include 

using namespace std;

namespace tlanyan {

 string Log::datetimeFormat = "%F %T";

 Log::Log()
 {
 }

 void Log::info(const char* message) {
  cout << getCurrentTime() << " [info] " << message << endl;
 }

 void Log::debug(const char* message) {
#if DEBUG
  cout << getCurrentTime() << " [debug] " << message;
#endif;
 }

 const char* Log::getCurrentTime()
 {
  //locale::global(locale("zh_CN.utf8"));
  time_t t = time(NULL);
  char mbstr[512];
  if (strftime(mbstr,sizeof(mbstr),Log::datetimeFormat.c_str(),localtime(&t))) {
   return mbstr;
  }
  
  cerr << "獲取或格式化時間錯誤!" << endl;

  exit(1);
 }

 Log::~Log()
 {
 }
}

// 呼叫示例:
Log::info("program begins...");

通過檢視Log,定位到了耗時長的過程。

  • 第一步,目測程式原始碼,找出問題所在。該段程式碼比較好理解,主要是進行資料初始化和打標籤。程式中規中矩,都是操控記憶體中的陣列,沒有磁碟、網路、程序通訊等耗時呼叫。審查程式碼中發現第一個問題:記憶體重分配。程式聲明瞭vector,沒有指定大小,後續程式碼中使用push_back對陣列的每一項進行賦值。記憶體分配和資料拷貝的代價是很大的,這應該是一個性能點。修改程式碼,宣告時指定陣列大小。編譯並執行程式,結果表明省下了30%的耗時。
  • 第二步,統計程式碼的工作量。耗時過程的初始化資料量,大概是整個資料量的10%,就算其中內嵌了兩層迴圈,也不應該耗時如此多。為了檢視是否有額外工作量,加入了計數器。執行結果顯示,該段函式的計算量不大,耗時長應該有其他的原因。
  • 第三步,根據經驗判斷是快取失效導致。第一反應是用valgrind檢視快取命中,但valgrind模擬執行的效率太差,幾個小時後kill掉放棄了。目測程式原始碼,發現很多資料都是從全域性記憶體讀取,沒有充分利用快取。修改程式碼,使用區域性變數快取全域性資料,接下來程式碼中的資料使用快取資料。經過測試,效果非常明顯,提升了50%的效率。
  • 第四步,查詢其他效能熱點。經過幾次小的調優測試,發現一些全域性記憶體訪問不可避免(隨機訪問,無法利用快取),按照目前的方式難以繼續優化。要大幅降低耗時需要重寫演算法,目前無法保證對演算法和程式意圖十分了解,遂暫時作罷。

優化前後的結果對比:中等資料規模下,耗時從8'43"降到3'25";大資料量下,耗時從4h38'44"降到1h49'21"(注:使用自己的機器測試,CPU主頻3.46GHz,比中科院和天河二號叢集的CPU主頻都要高,所以耗時短)。從資料看出,效果還是很明顯的。

以上就是C++ 程式優化歷程總結的詳細內容,更多關於C++ 程式優化的資料請關注我們其它相關文章!