圖像處理中卷積是基礎操作(模糊、銳化、邊緣檢測等)。Matlab conv2 極快(3000×3000 灰度圖,15×15 核約 170ms)。本文探討如何用 C++ 實現高性能任意核卷積。
for (y=0; y問題:緩存未命中嚴重,邊界判斷分支多,無法向量化。
優化策略
1. SSE 向量化乘累加
將卷積核每行填充至 4 的倍數(
Pad4(KW)),用_mm_malloc16 字節對齊。核心函數MultiplySSE:
- 核長 ≥16 時,4 路 SSE 並行(循環展開 4 次),最後合併 4 個
__m128求和。- 餘數部分用單路 SSE 處理。
2. 滑動窗口內存重用
預先構建擴展圖像(四周鏡像/複製填充),避免邊界判斷。分配
Kernel[PadConvLine × ExpHeight]存儲當前列所有像素的卷積窗口數據(已填充對齊)。
- 第一列:直接從擴展圖拷貝構建。
- 後續列:
memmove整體左移一位,只需更新最右一列新數據。每列內沿行方向滑動時,
Kernel指針每行遞增PadConvLine,直接調用MultiplySSE。3. 代碼關鍵片段
// 卷積核對齊填充 float *Conv16 = (float*)_mm_malloc(PadConvLine * ConvH * sizeof(float), 16); for (int y=0; y性能結果
測試環境:i5 CPU,3000×3000 灰度圖,15×15 核。本實現約 360ms,Matlab 約 170ms(差距約 2×)。作者指出 FFT 在小核(<50×50)下不如直接卷積快。
總結
結合 SSE 向量化、內存佈局優化、滑動窗口重用,可實現接近 Matlab 的任意核卷積性能。代碼較長但邏輯清晰,適合高性能圖像處理庫開發。