图解稀疏矩阵存储:从COO到CSR/CSC的压缩原理与内存布局

稀疏矩阵的CSR存储方式 稀疏矩阵的存储方式稀疏矩阵的存储方式CSR(compressed sparse row) 稀疏矩阵的存储方式 稀疏矩阵是数值计算中普遍存在的一类矩阵,主要特点是绝大部分的矩阵元为零。对于矩阵维度比较小的情况,利用稀疏矩阵特殊性并不能完全发挥优势。然而对于大型矩阵,例如矩阵维度超过10000,那么稀疏矩阵不仅节省存储空间,并且可以让线性代数算法得到极大的加速。比如大部分稀疏矩阵的算法均基于递推方法求解,即主要依赖于矩阵矢量乘法,这样很容易知道利用稀疏性可以优化该类算法的时间复杂度。 稀疏矩阵的存储格式往往依赖 阅读详情

图解稀疏矩阵存储:从COO到CSR/CSC的压缩原理与内存布局

如果你处理过大规模图数据、推荐系统或者机器学习模型,大概率已经和稀疏矩阵打过交道。想象一下,一个百万维的用户-物品交互矩阵,99.9%的元素都是零,如果还用传统的二维数组去存,内存瞬间就会被撑爆。这时候,稀疏矩阵存储格式就成了救星。

但问题来了,COO、CSR、CSC这些名词听起来就让人头大,更别说它们背后那些精巧的压缩原理和内存布局设计了。网上的教程要么是干巴巴的概念罗列,要么是公式推导让人望而生畏,真正从工程实现角度讲清楚“为什么这样设计”、“内存里到底长什么样”的内容少之又少。

这篇文章就是为你准备的。我们不只讲概念,更要通过可视化的方式,一步步拆解COO如何“压缩”成CSR,分析每种格式在内存中的真实排布,甚至深入到CUDA核函数里看它们是怎么被高效访问的。无论你是算法工程师需要优化模型推理速度,还是系统开发人员要设计高性能计算库,这些底层细节都至关重要。

1. 从最直观的COO开始:为什么需要压缩?

让我们先从一个简单的4x4稀疏矩阵入手,这个矩阵有9个非零元素:

[[1, 7, 0, 0],
 [0, 2, 8, 0],
 [5, 0, 3, 9],
 [0, 6, 0, 4]]

COO(Coordinate Format,坐标格式) 的存储思路非常直接:既然大部分元素都是零,那我就只记那些非零的。每个非零元素用一个三元组 (行索引, 列索引, 值) 来表示。

用Python的SciPy来构建这个矩阵,你能清晰地看到三个数组:

import numpy as np
from scipy.sparse import coo_matrix

# 构建COO格式的稀疏矩阵
row  = np.array([0, 0, 1, 1, 2, 2, 2, 3, 3])
col  = np.array([0, 1, 1, 2, 0, 2, 3, 1, 3])
data = np.array([1, 7, 2, 8, 5, 3, 9, 6, 4])

coo = coo_matrix((data, (row, col)), shape=(4, 4))
print("行索引数组:", coo.row)
print("列索引数组:", coo.col)
print("值数组:", coo.data)

输出结果就是上面那三个数组。在内存里,COO通常这样布局:

内存地址增长方向 →
[行索引] 0, 0, 1, 1, 2, 2, 2, 3, 3
[列索引] 0, 1, 1, 2, 0, 2, 3, 1, 3  
[值]     1, 7, 2, 8, 5, 3, 9, 6, 4

注意:COO的三个数组通常是分开存储的,但有些实现为了更好的局部性,会把三个值打包成一个结构体数组。这在某些CPU架构上能提升缓存命中率。

COO的优势很明显:构建极其灵活。你可以乱序添加元素,最后再排序;删除元素也简单,直接从数组里移除就行。很多文件格式(如Matrix Market)和网络传输协议都用COO,就是因为它的简单直观。

但COO有个致命问题:冗余存储。看上面的行索引数组,第0行的两个元素都存了0,第2行的三个元素都存了2。当矩阵行数很多时,这种重复存储会造成巨大的空间浪费。更重要的是,这种存储方式不利于按行快速访问。如果你想获取第2行的所有元素,必须扫描整个行索引数组,时间复杂度是O(nnz),其中nnz是非零元素个数。

2. CSR的压缩魔法:消除行索引冗余

CSR(Compressed Sparse Row,压缩稀疏行)格式的核心思想就是:既然同一行的元素行索引都一样,那我为什么不只存一次呢?

2.1 压缩原理图解

让我们一步步看COO如何变成CSR。还是上面那个矩阵,COO的三元组按行主序排列后是这样的:

(0,0,1), (0,1,7), (1,1,2), (1,2,8), (2,0,5), (2,2,3), (2,3,9), (3,1,6), (3,3,4)

CSR的压缩分为三步:

  1. 保留值和列索引:data和col_indices数组直接从COO继承
  2. 压缩行索引:不再存储每个元素的行号,而是记录每行第一个非零元素在data数组中的起始位置
  3. 添加哨兵:在行指针数组末尾加一个元素,值为非零元素总数,方便边界检查

转换后的CSR三个数组为:

row_ptr = [0, 2, 4, 7, 9]  # 行指针数组,长度=行数+1
col_ind = [0, 1, 1, 2, 0, 2, 3, 1, 3]  # 列索引数组
values  = [1, 7, 2, 8, 5, 3, 9, 6, 4]  # 值数组

这个row_ptr数组怎么理解?它表示:

  • 第0行非零元素在values[0:2](左闭右开区间)
  • 第1行在values[2:4]
  • 第2行在values[4:7]
  • 第3行在values[7:9]

2.2 内存布局与对齐策略

在真实系统中,CSR的三个数组在内存中的排布很有讲究。高性能计算库通常会考虑内存对齐,因为现代CPU和GPU的向量化指令(如AVX-512)要求数据按特定边界对齐才能发挥最大性能。

一个典型的优化布局是这样的:

内存布局示例(假设64字节缓存行对齐):
地址0x00: [row_ptr] 0, 2, 4, 7, 9, 0, 0, 0... (填充到64字节边界)
地址0x40: [col_ind] 0, 1, 1, 2, 0, 2, 3, 1, 3, 0, 0... (填充)
地址0x80: [values]  1.0, 7.0, 2.0, 8.0, 5.0, 3.0, 9.0, 6.0, 4.0... (填充)

为什么这么设计?考虑矩阵-向量乘法 y = A * x 的CSR实现:

// CSR格式的SpMV(稀疏矩阵-向量乘)核心计算
for (int i = 0; i < num_rows; i++) {
    double sum = 0.0;
    for (int j = row_ptr[i]; j < row_ptr[i+1]; j++) {
        sum += values[j] * x[col_ind[j]];  // 关键内存访问模式
    }
    y[i] = sum;
}

在这个循环中,对values[j]和col_ind[j]的访问是顺序访问,缓存友好。但对x[col_ind[j]]的访问是随机访问,因为列索引可能任意分布。这就是为什么CSR格式中,如果列索引是乱序的,性能会急剧下降。

2.3 列索引排序的重要性

很多高性能库在构建CSR时,会额外做一步:对每行内的列索引进行排序。虽然这增加了构建开销,但能带来显著的性能提升:

列索引状态 缓存命中率 预取效果 适合场景
完全乱序 低 差 动态构建,
COO、CSR、CSC稀疏矩阵存储方式 稀疏矩阵是一种大部分元素为零的矩阵,因此使用特殊的数据结构来存储稀疏矩阵可以节省内存并提高计算效率。 阅读详情

相关推荐

稀疏矩阵存储格式总结+存储效率对比:COO,CSR,DIA,ELL,HYB

稀疏矩阵是指矩阵中的元素大部分是0的矩阵,事实上,实际问题中大规模矩阵基本上都是稀疏矩阵,很多稀疏度在90%甚至99%以上。因此我们需要有高效的稀疏矩阵存储格式。本文总结几种典型的格式:COO,CSR,DIA,ELL,HYB。 (1)Coordinate(COO) 这是最简单的一种格式,每一个元素需要用一个三元组来表示,分别是(行号,列号,数值),对应上图右边的一列。这种方式简单,但...

weixin_33862514的博客 1364

项目管理工具project软件学习(五) - 创建WBS、设置任务依赖关系

1. 任务模式,设置自动计划。首先打开project软件,创建空白项目,先把新任务设置成【自动计划】,有以下两种方案: 方案一: 左下角点击改成【自动计划】 方案二: 【文件->选项->日程】 2. 创建WBS词典,下图是之前我们一个小模块的部分功能的schedule,拿来做例子去创建WBS 把上面任务输入到project里,创建WBS,如下 3. 上图...

weixin_40546390的博客 6147

掌握Project 2013:全面项目管理教程

项目管理作为一门科学,涵盖了从项目启动、规划、执行、监控到收尾的整个过程。掌握项目管理的原则和工具对于任何专业人士都是一个加分项,尤其是对于那些希望在管理层面提升自己的IT从业者。微软的Project2013是业界广泛使用的一个项目管理工具,它提供了强大的功能来辅助项目管理的各个环节。Project2013在项目管理软件中具有重要的地位,它的功能全面,界面直观,使得项目规划和管理变得更为高效。通过学习Project2013,项目管理者可以更好地管理项目进度、资源分配和成本控制。

weixin_30481539的博客 744

产业园区如何高效对接企业技术需求与高校科研成果?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

飞书日历同步Outlook翻车?我踩过的坑和最终用Google Calendar成功的完整配置记录

本文详细记录了从Outlook日历同步到飞书时遇到的常见问题及解决方案,特别是通过Google Calendar实现稳定同步的完整配置流程。文章揭示了Outlook同步方案易翻车的原因,并提供了Google Calendar的避坑指南、高级技巧和企业级部署建议,帮助用户高效实现日历同步。

weixin_33724046的博客 313

R语言dlnm包避坑指南:手把手教你配置交叉基矩阵(附温度分层与滞后多项式设置)

本文详细介绍了R语言dlnm包在配置交叉基矩阵时的实用技巧与避坑指南,特别针对温度分层与滞后多项式设置提供了具体参数配置建议。通过解析`crossbasis()`函数的核心参数、温度分析的分层策略以及不同基函数的适用场景,帮助研究者高效构建分布滞后非线性模型,避免常见错误并优化模型性能。

weixin_34094282的博客 401

逆向分析第一步:如何从HEX文件‘还原’出单片机的原始程序与数据?

本文详细解析了如何从HEX文件逆向分析出单片机的原始程序与数据,涵盖了固件逆向的底层逻辑与实践。通过介绍HEX文件的结构、内存映像重建技术以及专业工具链的使用,帮助读者掌握从十六进制数据到可执行代码的完整流程,适用于嵌入式系统开发和逆向工程领域。

weixin_29745609的博客 317

BUCK电路三种工作模式全解析:CCM、BCM、DCM到底怎么选?

本文深入解析BUCK电路的CCM、DCM和BCM三种工作模式,通过对比其电流波形、效率、纹波及环路特性,提供基于计算公式的量化判断方法。文章结合电池供电、高精度模拟等具体应用场景,给出明确的模式选型策略与实战设计指南,帮助工程师根据核心需求做出最优决策。

ee345的博客 486

绝缘检测是什么? 绝缘检测原理 绝缘检测检测的是什么?那个量?电压?电流?电阻?

绝缘电阻是电气设备和电气线路最基本的绝缘指标。对于低压电气装置的交接试验,常温下电动机、配电设备和配电线路的绝缘电阻不应低于0.5MΩ(对于运行中的设备和线路,绝缘电阻不应低于1MΩ/kV)。 绝缘电阻的正确测量方法 现代生活日新月异,人们一刻也离不开电。在用电过程中就存在着用电安全问题,在电器设备中,例如电机、电缆、家用电器等。 影响因素 环境温湿度 一般材料的绝缘电阻值随环境温湿度的升高而减小。相对而言,表面电阻(率)对环境湿度比较敏感,而体电阻(率)则对温度较为敏感。 湿度增加,表面泄漏增大,导体电导

dianqicyuyan的博客 2万+

基于Simulink的光储系统黑启动能力仿真

本文基于Simulink平台构建了光储系统黑启动仿真模型,详细阐述了储能VF控制、光伏孤岛MPPT和同步并网等核心控制策略。通过分阶段协调控制(储能启动→关键负载→光伏接入→非关键负载→同步并网),实现了60秒内恢复供电、母线电压波动<5%的性能指标。仿真结果表明,协调控制策略相比无序启动可显著提升系统稳定性,避免电压崩溃和负载跳闸。文章还提供了完整的建模步骤、核心代码及进阶优化方向,为微电网应急供电设计提供了实用参考。该模型适用于光伏储能系统的黑启动能力验证和优化研究。

amy_mhd的博客 106

AI编程工具深度对比:Cursor、Copilot、Trae与Claude Code,2025年开发者该如何选择?

2025年AI编程工具市场已形成四大主力阵营:Cursor(AI原生IDE)、GitHub Copilot(行业标准)、Trae(中国免费方案)和Claude Code(终端交互)。核心差异体现在技术能力(代码生成准确率85%-95%)、智能体协作程度和上下文处理能力(8K-200K tokens)。用户体验方面,Trae对中文支持最佳且免费,Copilot企业集成强,Cursor平衡易用与功能,Claude Code适合高阶开发者。实际测试显示,不同工具在原型开发、算法实现等场景各有优势

fudaihb的博客 6496

Android软键盘系统深度解析:架构、原理与实现

Android软键盘系统深度解析:架构与实现原理 本文系统剖析了Android软键盘的核心工作机制。作为系统级输入服务,软键盘具有双重属性:既是可安装的独立应用,又深度集成于系统框架中。文章详细解读了软键盘的系统架构,包括其与InputMethodManagerService(IMMS)和WindowManagerService(WMS)的交互机制,以及通过InputConnection实现的跨进程通信流程。同时分析了输入法窗口的特殊管理策略、布局调整模式,并深入探讨了输入预测引擎的实现原理,包括词典加载、

保持专注,保持热爱 115

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

上一篇: SpringBoot项目实战:用Guava Cache优化高频查询接口(附性能对比)
下一篇: 国自然热点 | CUT&Tag技术揭示H3K18la修饰在肿瘤微环境中的动态调控机制
algae
博客等级 码龄19年 1379粉丝 1719原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值