首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C 語言效能優化:減少運算量的兩大核心策略

     編輯:關於C語言

前言

程式優化的第二大方向 (第一是減少記憶體存取) 是**減少 CPU 運算指令數**。本文歸納兩大核心思路:演算法層面降低複雜度與實作層面消除冗餘運算。

策略一:演算法層面 — 降低時間複雜度

場景朴素做法優化演算法複雜度提升
查找線性掃描雜湊表 / 二分搜尋 / TrieO(n) → O(1) / O(log n)
排序氣泡/插入快速排序 / 合併排序 / 基數排序O(n²) → O(n log n)
字串匹配暴力比對KMP / Boyer-Moore / AC 自動機O(nm) → O(n+m)
圖最短路徑Floyd-WarshallDijkstra / A* / SPFAO(V³) → O(E log V)
動態規劃遞迴重複計算備忘錄 / 底向上 DP / 狀態壓縮指數 → 多項式

鐵律:**演算法優化永遠優於微優化**。選對資料結構與演算法,效能常提升數量級。

策略二:實作層面 — 消除冗餘運算

1. 將不變量移出迴圈 (Loop-Invariant Code Motion)


/* 朴素 */
for (int i = 0; i < n; ++i) {
    double r = sqrt(a * a + b * b);  // a,b 不變,每次都算
    result[i] = r * data[i];
}

/* 優化 */
double r = sqrt(a * a + b * b);      // 提到迴圈外
for (int i = 0; i < n; ++i) {
    result[i] = r * data[i];
}

現代編譯器 `-O2` 會自動完成,但複雜表達式 (函數呼叫、全域變數) 常漏優化,**手動提取更保險**。

2. 強度削減

昂貴運算替代方案適用場景
乘法/除法移位/加法/查表乘以 2 的冪、除以常數
取模 % n& (n-1) (n 為 2 的冪)環狀緩衝區索引
浮點數 sqrt查表 / 快速倒數平方根圖形/物理模擬
三角函數查表 / 多項式逼近音訊/訊號處理

/* 環狀緩衝區索引優化 */
#define MASK (BUFFER_SIZE - 1)  // BUFFER_SIZE 必須是 2 的冪
index = (index + 1) & MASK;     // 替代 index = (index + 1) % BUFFER_SIZE

3. 避免重複計算子表達式 (Common Subexpression Elimination)


/* 朴素 */
x = a * b + c;
y = a * b - d;

/* 優化 */
tmp = a * b;
x = tmp + c;
y = tmp - d;

編譯器 `-O1` 以上通常自動處理,但跨基本區塊或含函數呼叫時常失效。

4. 預計算與查表


/* 編譯期/啟動期建立查表 */
static const uint8_t popcount[256] = {
    0,1,1,2,1,2,2,3, ...  // 0~255 各數字的 1-bit 個數
};

/* 執行期 O(1) 計算 32-bit 整數 population count */
int popcnt32(uint32_t x) {
    return popcount[x & 0xFF] +
           popcount[(x >> 8) & 0xFF] +
           popcount[(x >> 16) & 0xFF] +
           popcount[x >> 24];
}

5. 減少函數呼叫開銷

  • 熱點函數加 `inline` / `static inline` (頭文件定義)。
  • 避免迴圈內呼叫虛函數/函數指標 (間接跳轉阻礙內聯)。
  • 將小函數併入迴圈主體 (手動內聯)。

實戰檢查清單

  1. Profiling 確認熱點 (perf, gprof, VTune)。
  2. 熱點迴圈檢查:不變量是否外提?強度可否削減?
  3. 資料結構是否適合存取模式 (陣列 vs 鏈表、AoS vs SoA)?
  4. 編譯器優化選項:`-O2 -march=native -flto` (釋出版)。
  5. 向量化檢查:`-fopt-info-vec` 確認 SIMD 生成。

結語

減少運算量的最高原則:**先換演算法,再改實作**。演算法決定複雜度上限,實作技巧 (不變量外提、強度削減、查表、內聯) 在常數因子上榨乾 CPU。永遠用 **Profiler 數據說話**,別靠直覺優化非熱點代碼。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved