减少稀疏矩阵的内存
一种方法(他们在您链接的第一篇论文中提到,但值得强调)是块压缩稀疏行 (BCSR) 存储格式。如果您的问题造成密集n×n块(例如在每个节点具有多个自由度的 FEM 中很常见),您修改典型的 CSR (CSC) 存储方案以仅存储块的单个列(行)索引。这将索引向量的存储需求减少了一个因子n2. 如果你要存储3×3块,这将索引向量所需的内存减少了约 90%,这比使用任何类型的位打包技巧节省的内存要多得多。
可以在这里找到更完整的格式描述:http:
//www.netlib.org/utk/people/JackDongarra/etemplates/node375.html
此外,在稀疏矩阵中存储密集块允许您使用 SSE 或 AVX 指令对矩阵向量乘法进行向量化,但您可能不会在这里看到巨大的加速,因为正如您所指出的,您仍然会受到内存限制.
如果您的问题没有产生像 FEM 一样完美的 BCSR 结构,那么您仍然可以使用该技术而不会产生未对齐块的内存开销。本文展示了一个不需要块以多个n列(并且还解释了我所说的未对齐块的内存开销的意思)。
https://bebop.cs.berkeley.edu/pubs/vuduc2005-ubcsr-split.pdf
当然,没有什么可以阻止您使用重新排序的 BCSR 矩阵来玩位打包游戏以进一步降低内存需求,但您可能应该先选择容易实现的目标。
一般的位打包
如果您对位打包的应用特别感兴趣,这在 LLVM 项目中非常积极。它的一个(聪明?)想法是使用他们所谓的 PointerIntPair,它将一个指针和一个小整数一起存储在单个指针的空间中。这里的想法是利用这一事实(在 linux x64 系统上),malloc 返回的指针是 16 字节对齐的,这使您在底部有 4 位可以处理。他们使用这个想法做各种疯狂的事情,构建复杂的数据结构,这些数据结构存在于单个指针的空间中。这是几年前由 LLVM 优化器专家之一进行的一次有趣的会议演讲。他在 22:00 开始谈论这个问题。不过,公平的警告是:这是在一个 C++ 会议上,因此涉及到大量毫不掩饰的复杂 C++。
https://www.youtube.com/watch?v=vElZc6zSIXM&t=22m&ab_channel=CppCon