【C++游戲引擎開發】《線性代數》(3):矩陣乘法的SIMD優化與轉置加速

一、矩陣乘法數學原理與性能瓶頸

1.1 數學原理

矩陣乘法定義為:給定兩個矩陣 A ( m × n ) \mathrm{A}(m×n) Am×n B ( n × p ) \mathrm{B}(n×p) Bn×p,它們的乘積 C = A × B \mathrm{C}=A×B C=A×B 是一個 m × p \mathrm{m}×p m×p 的矩陣,其中:

C i , j = ∑ k = 1 n A i , k ? B k , j C_{i,j} = \sum_{k=1}^{n} A_{i,k} \cdot B_{k,j} Ci,j?=k=1n?Ai,k??Bk,j?

每個元素 C [ i ] [ j ] C[i][j] C[i][j] 需要 n n n 次乘法和 n ? 1 n-1 n?1 次加法,總時間復雜度為 O ( m n p ) O(mnp) O(mnp) 。對于兩個 n × n n×n n×n 方陣,時間復雜度為 O ( n 3 ) O(n^3) O(n3)

2.2 ?性能問題

2.2.1 內存訪問效率
  • ?緩存未命中:大矩陣無法完全放入緩存,導致頻繁訪問內存,增加延遲。
  • 非連續訪問:訪問 B B B的列時,若存儲為行主序,會導致緩存不友好。
2.2.2 并行化效率
  • ?任務分配不均:靜態分配可能導致負載不均衡。
  • 同步開銷:多線程間同步可能引入額外開銷。
2.2.3 指令級并行與向量化
  • SIMD利用率低:未充分利用向量指令(如AVX、NEON)。
2.2.4 循環結構與數據布局
  • 低效循環順序:傳統三重循環(i-j-k)導致內存訪問不連續。

2.3 優化策略

  1. 分塊處理:將矩陣劃分為適合緩存的小塊,減少內存訪問。
  2. 多線程并行:使用OpenMP、pthread等多線程庫并行計算。
  3. SIMD向量化:利用AVX/SSE指令加速計算。
  4. 數據布局優化:轉置矩陣 B B B 或調整存儲順序(行/列主序)。

二、分塊策略優化(Cache-Friendly)?

分塊(Tiling)策略是優化矩陣乘法性能的核心技術之一,其核心思想是通過**數據局部性(Locality)**?提升緩存利用率,減少內存訪問延遲。

2.1 為什么需要分塊?

矩陣乘法的樸素實現(三重循環)通常存在以下問題:

  • 內存訪問模式差:對矩陣 B B B的列訪問(行主序存儲下)不連續,導致**緩存行(Cache Line)**利用率低。
  • ?數據重用率低:每個元素 A [ i ] [ k ] A[i][k] A[i][k] B [ k ] [ j ] B[k][j] B[k][j]僅被使用一次,無法利用緩存的時間局部性(Temporal Locality)。
  • 緩存容量不足:當矩陣大小超過緩存容量時,頻繁的緩存未命中(Cache Miss)會觸發內存訪問,導致性能驟降。
    分塊策略通過將大矩陣拆分為適合緩存的小塊,使得每個小塊的數據能長時間駐留在緩存中,從而提升數據重用率。

2.2 分塊策略的原理

2.2.1 數據局部性優化
  • 時間局部性:同一塊內的數據被多次使用(例如,分塊后 A A A的子塊行與 B B B的子塊列多次參與計算)。
  • ?空間局部性:連續訪問內存中的數據(例如,按行優先順序訪問子塊內的元素)。
2.2.2 分塊步驟
  1. 劃分矩陣:將矩陣 A A A B B B劃分為大小為 T × T T×T T×T的子塊(Block), A A A按行分塊, B B B按列分塊, C C C對應分塊,分塊大小 T T T需根據緩存容量(如L1/L2 Cache大小)調整。
  2. 分塊乘法:對每個子塊執行矩陣乘法(子塊乘積累加到 C C C的對應位置)。
  3. 循環順序調整:將循環順序從樸素的 ?i-j-k 調整為 ?i-k-j,優先處理分塊內的計算。
2.2.3 分塊后的計算流程
for i in 0 to m step T:           # 分塊行循環for j in 0 to p step T:       # 分塊列循環for k in 0 to n step T:   # 分塊中間循環# 計算子塊 C[i:i+T, j:j+T] += A[i:i+T, k:k+T] * B[k:k+T, j:j+T]for ii in i to i+T:   # 子塊內行循環for kk in k to k+T:for jj in j to j+T:C[ii][jj] += A[ii][kk] * B[kk][jj]

2.3 示例代碼

#include <immintrin.h>void block_matmul(int m, int n, int p, float* A, float* B, float* C) {const int T = 64; // 分塊大小for (int i = 0; i < m; i += T) {for (int j = 0; j < p; j += T) {for (int k = 0; k < n; k += T) {// 子塊范圍int i_end = std::min(i + T, m);int j_end = std::min(j + T, p);int k_end = std::min(k + T, n);// 子塊內計算(使用AVX2)for (int ii = i; ii < i_end; ii++) {for (int kk = k; kk < k_end; kk++) {__m256 a = _mm256_broadcast_ss(&A[ii * n + kk]);for (int jj = j; jj < j_end; jj += 8) {__m256 b = _mm256_loadu_ps(&B[kk * p + jj]);__m256 c = _mm256_loadu_ps(&C[ii * p + jj]);c = _mm256_fmadd_ps(a, b, c);_mm256_storeu_ps(&C[ii * p + jj], c);}}}}}}
}

三、矩陣轉置

矩陣轉置是線性代數中的基本操作,指將矩陣的行和列互換。具體來說,對于一個 m × n m×n m×n的矩陣 A A A,其轉置矩陣 A T A^T AT是一個 n × m n×m n×m的矩陣。

3.1 8x8塊轉置代碼實現

void transpose_8x8_block(size_t i, size_t j, Matrix& result) const {const float* src = data_ + i * cols_ + j;__m256 row0 = _mm256_loadu_ps(src + 0 * cols_);__m256 row1 = _mm256_loadu_ps(src + 1 * cols_);__m256 row2 = _mm256_loadu_ps(src + 2 * cols_);__m256 row3 = _mm256_loadu_ps(src + 3 * cols_);__m256 row4 = _mm256_loadu_ps(src + 4 * cols_);__m256 row5 = _mm256_loadu_ps(src + 5 * cols_);__m256 row6 = _mm256_loadu_ps

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/75275.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/75275.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/75275.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Vue Transition組件類名+TailwindCSS

#本文教學結合TailwindCSS實現一個Transition動畫的例子# 舉例代碼&#xff1a; <transition enter-active-class"transition-all duration-300 ease-out"enter-from-class"opacity-0 translate-y-[-10px]"enter-to-class"opacity-100 translate-…

技術回顧day2

1.獲取文件列表 流程&#xff1a;前端根據查詢條件封裝查詢信息&#xff0c;后端接收后進行封裝&#xff0c;封裝為FileInfoQuery,根據fileInfoQuery使用mybatis的動態sql來進行查詢。 2.文件分片上傳 每次上傳需要上傳包括(文件名字&#xff0c;文件&#xff0c;md5值&#…

DeepSeek-R1 模型現已在亞馬遜云科技上提供

2025年3月10日更新—DeepSeek-R1現已作為完全托管的無服務器模型在Amazon Bedrock上提供。 2025年2月5日更新—DeepSeek-R1 Distill Llama 和 Qwen模型現已在Amazon Bedrock Marketplace和Amazon SageMaker JumpStart中提供。 在最近的Amazon re:Invent大會上&#xff0c;亞馬…

STP --- 生成樹協議

協議信息 配置 BPDU Protocol identifier&#xff1a;協議標識 Version&#xff1a;協議版本&#xff1a;STP 為 0&#xff0c;RSTP 為 2&#xff0c;MSTP 為 3 type&#xff1a; BPDU 類型 Flag&#xff1a; 標志位 Root ID&#xff1a; 根橋 ID&#xff0c;由兩字節的優…

Ansible playbook-ansible劇本

一.playbook介紹 便于功能的重復使用 本質上就是文本文件&#xff0c;一般都是以.yml結尾的文本文件。 1.遵循YAML語法 1.要求同級別代碼要有相同縮進&#xff0c;建議4個空格。【同級別代碼是同一邏輯的代碼】 在計算機看來空格和Tob鍵是兩個不同的字符。 2.一個鍵對應一…

python的基礎入門

初識Python 什么是Python Python是1門程序設計語言。在開發者眼里&#xff0c;語言可以分為3類&#xff1a; 自然語言&#xff1a;人能聽懂的語言&#xff0c;例如漢語&#xff0c;英語&#xff0c;法語等等。機器語言&#xff1a;機器能聽懂的語言&#xff0c;機器只能聽懂0…

MD編輯器中的段落縮進怎么操作

在 Markdown&#xff08;MD&#xff09;編輯器中&#xff0c;段落的縮進通常可以通過 HTML 空格符、Markdown 列表縮進、代碼塊縮進等方式 實現。以下是幾種常見的段落縮進方法&#xff1a; 1. 使用全角空格 ( ) 在一些 Markdown 編輯器&#xff08;如 Typora&#xff09;中&…

8.neo4j圖數據庫python操作

使用圖數據庫的原因 圖數據庫使用neo4j的原因&#xff1a;neo4j使用率高&#xff0c;模板好找&#xff0c;報錯能查。 紅樓夢人物關系圖地址 GraphNavigator neo4j學習手冊 https://www.w3cschool.cn/neo4j/neo4j_need_for_graph_databses.html CQL代表的是Cypher查詢語言…

[Lc6_記憶化搜索] 掃雷游戲 | 理解 遞歸vs記憶化搜索vs dp

目錄 ?1.掃雷游戲 題解 1.記憶化搜索 解法一&#xff1a;遞歸 解法二&#xff1a;記憶化搜索 解法三&#xff1a;動態規劃 ?1.掃雷游戲 (暴力模擬&#xff09; 鏈接&#xff1a;529. 掃雷游戲 讓我們一起來玩掃雷游戲&#xff01; 給你一個大小為 m x n 二維字符矩陣…

云原生周刊:Kubernetes v1.33 要來了

開源項目推薦 Tekton Tekton 是一個開源的 K8s 原生 CI/CD 系統&#xff0c;它為構建、測試和部署自動化工作流提供了強大而靈活的框架。Tekton 提供了一套標準化的 API 和自定義資源&#xff08;CRDs&#xff09;&#xff0c;使得開發者能夠在 K8s 集群中定義和管理 CI/CD 管…

服務新增節點、遷移筆記

文章目錄 基礎配置部分基礎配置-hosts基礎配置-jdk包準備基礎配置-jdk環境變量配置基礎配置-skywalking包 基礎配置-apollo配置。 # 文件夾及配置基礎配置-tomcat基礎配置-nginx基礎配置部分-磁盤掛載(這個也差點漏掉)。 防火墻部分防火墻部分-數據庫及腳本防火墻部分-redis防火…

第十一章:Python PIL庫-圖像處理

一、PIL庫簡介 PIL&#xff08;Python Imaging Library&#xff09;是一個功能強大的圖像處理庫&#xff0c;它提供了豐富的圖像處理功能&#xff0c;包括圖像的打開、處理和保存等操作。PIL支持多種圖像文件格式&#xff0c;如JPEG、PNG、BMP等&#xff0c;并且可以完成對圖像…

【編譯、鏈接與構建詳解】Makefile 與 CMakeLists 的作用

【編譯、鏈接與構建詳解】Makefile 與 CMakeLists 的作用 前言源代碼&#xff08;.c、.cpp&#xff09;編譯編譯的本質編輯的結果編譯器&#xff08;GCC、G、NVCC 等&#xff09; 目標文件&#xff08;.o&#xff09;什么是 .o 目標文件為什么單個 .o 目標文件不能直接執行&…

Ubuntu / Debian 創建快捷方式啟動提權

簡述 在 Linux 系統中&#xff0c;.desktop 文件是 桌面入口文件&#xff0c;用于在桌面環境&#xff08;如 GNOME、KDE&#xff09;中定義應用程序的啟動方式、圖標、名稱等信息。當你執行 touch idea.desktop 時&#xff0c;實際上創建了一個空的 .desktop 文件&#xff08;…

ISIS報文

IS-IS 報文 目錄 IS-IS 報文 一、報文類型與功能 二、報文結構解析 三、核心功能特性 四、典型應用場景 五、抓包數據分析 六、總結 IS-IS&#xff08;中間系統到中間系統&#xff09;協議報文是用于鏈路狀態路由協議中網絡設備間交換路由信息的關鍵載體&#xff0c;其設…

beikeshop多商戶跨境電商獨立站最新版v1.6.0版本源碼

一.介紹 beikeshop跨境電商獨立站最新版V1.6.0源碼 多商戶 多商家 多語言 多幣結算 本博主親測搭建代碼全開源質量相對來說很穩定的 二.服務器環境 系統&#xff1a;CentOS、 環境&#xff1a;PHP7.4 Nginx 1.21 MySQL 5.6 常見插件&#xff1a;fileinfo &#xff1b; re…

Redis批量操作詳解

一、原生批量命令&#xff08;MSET&#xff09; 適用場景&#xff1a;所有鍵的過期時間相同或無過期設置&#xff0c;且無需條件判斷。 方法&#xff1a; 將多個SET命令合并為MSET命令&#xff0c;但需要注意MSET的局限性&#xff08;無法設置過期時間&#xff0c;且所有鍵值對…

Spring Boot 集成實戰:AI 工具如何自動生成完整微服務模塊

在數字化轉型的浪潮中&#xff0c;開發效率和質量是企業競爭力的關鍵要素。飛算 JavaAI 作為一款創新的 AI 工具&#xff0c;能在 Spring Boot 開發中&#xff0c;自動生成完整微服務模塊&#xff0c;極大提升開發效率。下面&#xff0c;我們就詳細介紹如何借助飛算 JavaAI&…

算法 | 2024最新算法:斑翠鳥優化算法原理,公式,應用,算法改進研究綜述,matlab代碼

基于斑翠鳥優化算法的原理、應用及改進研究綜述 一、算法原理 斑翠鳥優化算法(Pied Kingfisher Optimizer, PKO)是2024年由Bouaouda等人提出的一種新型仿生智能優化算法,其靈感來源于斑翠鳥的捕食行為與共生關系。算法通過模擬斑翠鳥的棲息懸停、潛水捕魚及與其他生物的共生…

RabbitMQ高級特性--重試特性

目錄 1.重試配置 2.配置交換機&隊列 3.發送消息 4.消費消息 5. 運行程序觀察結果 6. 手動確認 注意&#xff1a; 在消息傳遞過程中, 可能會遇到各種問題, 如網絡故障, 服務不可用, 資源不足等, 這些問題可能導致消息處理失敗. 為了解決這些問題, RabbitMQ 提供了重試機制, …