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

1000×1000 矩陣乘法優化:分塊算法對比 MATLAB 性能分析

     編輯:關於C++

基準代碼:分塊矩陣乘法

const int m = 1000;
double *A = new double[m*m], *B = new double[m*m], *C = new double[m*m];
// 初始化為 1
for (int i = 0; i < m*m; ++i) { A[i] = 1; B[i] = 1; C[i] = 0; }

const int BF = 48;  // 分塊因子,可調優化
for (int jj = 0; jj < m; jj += BF)
    for (int kk = 0; kk < m; kk += BF)
        for (int i = 0; i < m; ++i) {
            int minj = min(jj + BF, m);
            int im = i * m;
            int mink = min(kk + BF, m);
            for (int j = jj; j < minj; ++j) {
                double r = 0;
                for (int k = kk; k < mink; ++k)
                    r += A[im + k] * B[k*m + j];
                C[im + j] += r;
            }
        }
delete[] A; delete[] B; delete[] C;

性能現狀

  • 該實現比 MATLAB 慢 1 倍(約 2x 時間)。
  • 網上 Fortran 分塊 dgemm 比 MATLAB 慢 0.5 倍(1.5x 時間)。
  • 目標:達到 MATLAB 同級性能(調用 Intel MKL/OpenBLAS 高度優化內核)。

關鍵優化方向

優化點說明預期收益
緩存友好訪問B 矩陣按列訪問導致缺失,需轉置或塊內連續訪問高
SIMD 向量化編譯器自動向量化需簡單循環,或手寫 AVX/SSE 內聯匯編高
寄存器分塊內層循環展開,多累加器隱藏延遲(如 4×4 微內核)高
多線程並行OpenMP 外層循環並行,NUMA 感知內存分配線性擴展
預取指令__builtin_prefetch 或硬件預取友好訪問模式中
調用優化庫直接鏈接 OpenBLAS/MKL/BLIS 的 cblas_dgemm最高(專家調優)

改進版雛形(單線程 + 緩存優化)

// 預轉置 B 矩陣,實現連續訪問
double *BT = new double[m*m];
for (int i = 0; i < m; ++i)
    for (int j = 0; j < m; ++j)
        BT[j*m + i] = B[i*m + j];

for (int jj = 0; jj < m; jj += BF)
    for (int kk = 0; kk < m; kk += BF)
        for (int i = 0; i < m; ++i) {
            int im = i * m;
            int minj = min(jj + BF, m);
            int mink = min(kk + BF, m);
            for (int j = jj; j < minj; ++j) {
                double r = 0;
                int jm = j * m;  // BT 行首
                for (int k = kk; k < mink; ++k)
                    r += A[im + k] * BT[jm + k];  // 連續訪問
                C[im + j] += r;
            }
        }
delete[] BT;

工程建議

  1. 生產環境直接用 OpenBLAS/MKL:cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, m, m, m, 1.0, A, m, B, m, 0.0, C, m);
  2. 自研教學/嵌入式無庫環境:參考 BLIS 框架實現微內核 + 多層分塊 + 多線程。
  3. 分塊因子 BF 需根據 L1/L2 緩存大小經驗調整(典型 32-128)。
  4. 編譯旗標:-O3 -march=native -ffast-math -funroll-loops(GCC/Clang),/O2 /arch:AVX2(MSVC)。
  5. 性能分析工具:perf、VTune、gprof 定位熱點與缺失。

結語

矩陣乘法優化是計算機體系結構、編譯器技術、數值線性代數交叉的經典課題。手寫高性能 GEMM 需深度理解硬體特性,工程實踐首選成熟數學庫,自研僅作教學或極端受限場景。

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