【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=1nAi,kBk,j

每个元素 C [ i ] [ j ] C[i][j] C[i][j] 需要 n n n 次乘法和 n − 1 n-1 n1 次加法,总时间复杂度为 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.mzph.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 提供了重试机制, …