矩陣乘法是線性代數基礎運算,亦是圖形學、機器學習、科學計算的核心。本文給出標準 O(n³) 三層循環實現,並說明維度匹配規則與優化方向。
設 A 為 m×n 矩陣,B 為 n×p 矩陣,乘積 C = A×B 為 m×p 矩陣,元素公式:
C[i][j] = Σ (A[i][k] * B[k][j]) , k=0..n-1
前提:A 的列數 == B 的行數。
public interface IMatrixMultiplier {
int[][] multiply(int[][] a, int[][] b);
}
public class MatrixMultiplier implements IMatrixMultiplier {
@Override
public int[][] multiply(int[][] a, int[][] b) {
// 1. 維度校驗
if (a == null || b == null || a.length == 0 || b.length == 0) {
throw new IllegalArgumentException("矩陣不能為空");
}
int aRows = a.length, aCols = a[0].length;
int bRows = b.length, bCols = b[0].length;
if (aCols != bRows) {
throw new IllegalArgumentException("A的列數(" + aCols + ")必須等於B的行數(" + bRows + ")");
}
// 2. 結果矩陣初始化
int[][] result = new int[aRows][bCols];
// 3. 標準三層循環
for (int i = 0; i < aRows; i++) {
for (int j = 0; j < bCols; j++) {
int sum = 0;
for (int k = 0; k < aCols; k++) {
sum += a[i][k] * b[k][j];
}
result[i][j] = sum;
}
}
return result;
}
}
a[i][k] 與 b[k][j] 的訪問模式對緩存友好度不同(b 列訪問非連續),可考慮轉置 B 提升緩存命中。int 乘法累加可能溢出,生產環境建議用 long 或 BigInteger。| 優化手段 | 原理 | 適用場景 |
|---|---|---|
| 分塊/分塊算法 | 將矩陣分塊適應 L1/L2 緩存,減少緩存未命中 | 大矩陣(>512×512) |
| Strassen 算法 | O(n^2.807) 遞歸分治,減少乘法次數 | 極大矩陣,數值穩定性要求不高 |
| 並行計算 | ForkJoinPool / 線程池並行計算不同行/塊 | 多核 CPU,矩陣較大 |
| 原生庫調用 | JNI 調用 OpenBLAS / MKL / cuBLAS (GPU) | 高性能計算、深度學習推理 |
public class MatrixMultiplierTest {
@Test
public void testMultiply() {
int[][] a = {{1, 2}, {3, 4}};
int[][] b = {{5, 6}, {7, 8}};
int[][] expected = {{19, 22}, {43, 50}};
assertArrayEquals(expected, new MatrixMultiplier().multiply(a, b));
}
@Test(expected = IllegalArgumentException.class)
public void testDimensionMismatch() {
new MatrixMultiplier().multiply(new int[][]{{1,2,3}}, new int[][]{{1},{2}}); // 3≠2
}
}
矩陣乘法雖基礎,卻是高性能計算的縮影。掌握標準實現、理解緩存行影響、知曉何時引入原生庫,是從「會寫代碼」到「寫好代碼」的關鍵一步。