我想知道是否有可能通过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分解中得到的行列式,我认为计算逆矩阵会更好。
答案 0 :(得分:1)
我不确定我要说的是否会对你有所帮助。但是在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
最后大量使用局部变量会导致调度程序在多个周期内运行块,因为每个块的寄存器文件不足以同时运行整个块。