Symmetric Matrix-Vector Multiplication with only lower triangular stored
Show older comments
I have a very big (n>1000000) sparse symmetric positive definite matrix A and I want to multiply it efficiently by a vector x. Only the lower triangular of matrix A is stored with function "sparse". Is there any function inbuilt or external that anyone knows of that takes as input only the lower triangular and performs the complete operation Ax without having to recover whole A (adding the strict upper triangular again)?
Thank you very much,
Jan
Accepted Answer
More Answers (1)
Clayton Gotberg
on 24 Apr 2021
If
is a symmetric matrix and
is the lower triangular part of the matrix and
is the upper triangular part of the matrix:
is the lower triangular part of the matrix and
is the upper triangular part of the matrix:
where the diagonal function only finds the diagonal elements of
. This is because of a few relations:


To save time and space on MATLAB (because the upper triangular matrix will take up much more space), take advantage of the relations:

To get:
Now, the MATLAB calculation is
A_times_x = A_LT*x+(x.'*A_LT).'+ diag(A_LT).*x;
This should only perform transposes on the smaller resultant matrices.
7 Comments
Jan
on 24 Apr 2021
This is a smart approach. To my surprise it is not faster than (A_LT.' * x) - at least in R2018b.
Clayton Gotberg
on 24 Apr 2021
If I'd spent a little less time on the LaTeX I might have gotten there first as well haha. I'm not sure what the etiquette is for this forum; since your answer was nearly the same as mine except earlier (and is now far more detailed) should I delete mine or leave it here?
I'm also surprised that (A_LT.' * x) and (x.' * A_LT).' evaluate in nearly the same time. I'd guess it might have something to do with the fact that the second operation has more layers, making it more difficult for MATLAB to interpret it correctly to apply shortcuts, but I have no real knowledge of MATLAB's backend. I'll have to trust MathWorks more the next time I'm doing operations over big data.
Bruno Luong
on 24 Apr 2021
"This should only perform transposes on the smaller resultant matrices.é
I believe MATLAB parse/egine is intelligent enought to call the corresponding BLAS that does not do any explicit transposition on both operants regardless if there is transposition operator or not.
Clayton Gotberg
on 24 Apr 2021
I ran my own small test in MATLAB R2020b, directly comparing (A_LT.' * x) and (x.' * A_LT).'. The attached .mat file has the x and A_sparse_tri I used.
function [T1,T2] = test_func(rep,x,A_sparse_tri) % keeping the same x and A
for k = 1:rep
tic
A_sparse_tri.'*x;
T1(k) = toc;
end
for k = 1:rep
tic
(x.'*A_sparse_tri);
T2(k) = toc;
end
end
T1_benchmark = [min(T1) mean(T1) max(T1)];
T2_benchmark = [min(T2) mean(T2) max(T2)];
performance = T2_benchmark-T1_benchmark
% Result for 10000 reps:
1000*[T1_benchmark;T2_benchmark] =
0.0320 0.0395 2.7669
0.0983 0.1005 0.3540
performance =
0.0000663 0.00006104 -0.00241290
So Jan's function is usually three times faster and it has the record for a minimum speed, but mine has the lowest maximum evaluation time. In the end I guess runtime depends on something deeply personal to your computer, but I would recommend Jan's function unless you need to keep evaluation time consistently low.
Jan
on 24 Apr 2021
@Clayton Gotberg: "I'm not sure what the etiquette is for this forum; since your answer was nearly the same as mine except earlier (and is now far more detailed) should I delete mine or leave it here?"
Please leave your answer here. Although the difference between the answers is small, it is valuable e.g. to see that (A.'*x) and (x.'*A).' are processed with the same speed.
The JIT acceleration can be tricky and can cause misleading timings. In your test code, the iterative growing of the T1 and T2 vectors can influence the timings. In some cases the JIT seems to perform a dead-code elimination, such that the expression (x.'*A_sparse_tri); is removed completely, because its output is not stored. Sometimes the JIT recognizes repeated code, such that the actual computation is performed once only. The function timeit is more accurate, but I'm still in doubt, whether providing anonymous functions introduce a bias also.
Bruno Luong
on 24 Apr 2021
Edited: Bruno Luong
on 24 Apr 2021
Might be you can experiment with this as well
reshape((x.'*A),[],1)
Clayton Gotberg
on 24 Apr 2021
I begin to understand why engineers are specifically trained and hired to test software. It's deeply interesting to get this peek into what MATLAB does to ensure I can keep writing ill-considered code.
Categories
Find more on Loops and Conditional Statements in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!