就地乔列斯基逆

In-place Cholesky inverse

本文关键字:乔列斯      更新时间:2023-10-16

我想知道是否有可能在不需要临时数组的情况下通过 Cholesky 分解获得矩阵的逆。到目前为止,我可以在不使用临时数组的情况下获得 cholesky 因式分解,但从那里我还没有找到一种方法来获得原始矩阵的逆矩阵,而无需重复到与原始矩阵相同维度的临时矩阵。即求解系统

A x_i = e_i, where e_i is the i-th column if the identity matrix.

我实际上遵循了一种稍微好一点的方法,如 http://arxiv.org/abs/1111.4144

中所述

一些背景:

我正在编写一个 (C/C++) CUDA 程序,其中每个线程计算相对较小的(20x20,在某些情况下为 40x40)协方差矩阵的逆函数和行列式,以及其他任务。在 CUDA 中使用数组不是很快,这就是为什么我想尽量减少它们的使用。当我编码就地 cholesky 分解并限制仅使用矩阵的较低条目时,我已经看到了一些重大改进,这就是为什么如果我设法摆脱方程求解部分中的临时数组,我希望会有一些改进,即如果算法使用临时变量作为至少更小的数组,那就可以了。

我知道,计算x = A^{-1} b,这正是我最终所做的,通过解决系统A x = b比反向计算更有效。但是由于我也需要行列式,在Cholesky分解中获得,我认为计算逆数会更好。

我不确定我要说的话是否会对你有所帮助。但是在 CUDA 中访问数组的成本可能为 16 倍,而成本仅为 1 倍。 这取决于内存排列和每个线程将执行的访问模式。

对我来说,假设我有 100 个线程,每个线程需要一个大小为 20x20 的整数/浮点数的矩阵。如果我是,你会毫不犹豫地只使用一个在所有线程之间共享的数组,每个线程将像这样访问第一个元素:

int iFirstElement = gArray[tid]; // where tid is the thread idx assuming this 1D,2D, or 3D I am sure you can calculate the tid easily.
//to access the second element you can use this:
int iSecondElement = gArray[numOfThreads * 1 + tid];
// to access the third element you can use this
int iSecondElement = gArray[numOfThreads * 2 + tid];

这样,您将增强内存访问模式,并且仅消耗 1X 而不是 16X 来访问内存。你可能认为全局内存是个坏主意,但相信我,事实并非如此。 你可以回到我发表的论文,在GPU上进行人脸检测,阅读更多关于内存访问模式的信息。

http://ijces.org/media/1Iss8-IJCES0402603_v4_iss2_47-55.pdf

最后,广泛使用局部变量将导致调度程序在多个周期中运行块,因为每个块的寄存器文件不足以同时运行整个块。