I need to repeatedly calculate f(x)=exp(A*x) for a small, variable column-vector x and a huge, constant matrix A (many rows, several columns). In other words, x little, but A*x lot. My problem sizes are such that A*x takes about the same amount of time as the exp () part.
In addition to expanding Taylor and pre-calculating the range of exp(y) values exp(y) provided that the range of y values of A*x is known), which I could not significantly speed up (while maintaining accuracy) with what MATLAB does on its own, I think of analytical repetition problems to be able to pre-calculate some values.
For example, I found that exp(A*x)_i = exp(\sum_j A_ij x_j) = \prod_j exp(A_ij x_j) = \prod_j exp(A_ij)^x_j
This would allow me to pre-compute exp(A) once, but the required looping would be as expensive as the original call to exp() , and multiplication (\ prod) would have to be done additionally.
Is there any other idea I could follow, or solutions in MATLAB that I might have missed?
Edit: some more details
A has a size of 26873856 by 81 (yes, it's huge), so x is 81 by 1. nnz(A) / numel(A) is 0.0012 , nnz(A*x) / numel(A*x) is 0.0075 . I already use a sparse matrix to represent A , however exp () of the sparse matrix is not yet sparse. That way I keep x not sparse, and I compute exp(full(A*x)) , which turned out to be as fast / slow as full(exp(A*x)) (I think A*x in any case is not sparse, since x is not sparse.) exp(full(A*sparse(x))) is a way to have sparse A*x , but slower. Even slower options are exp(A*sparse(x)) (with doubled memory effect for a non-sparse type matrix sparse) and full(exp(A*sparse(x)) (which again gives an unsharp result).
sx = sparse(x); tic, for i = 1 : 10, exp(full(A*x)); end, toc tic, for i = 1 : 10, full(exp(A*x)); end, toc tic, for i = 1 : 10, exp(full(A*sx)); end, toc tic, for i = 1 : 10, exp(A*sx); end, toc tic, for i = 1 : 10, full(exp(A*sx)); end, toc Elapsed time is 1.485935 seconds. Elapsed time is 1.511304 seconds. Elapsed time is 2.060104 seconds. Elapsed time is 3.194711 seconds. Elapsed time is 4.534749 seconds.
Yes, I am calculating the element-wise exp, I am updating the above equation to reflect this.
Another edit: I tried to be smart, with little success:
tic, for i = 1 : 10, B = exp(A*x); end, toc tic, for i = 1 : 10, C = 1 + full(spfun(@(x) exp(x) - 1, A * sx)); end, toc tic, for i = 1 : 10, D = 1 + full(spfun(@(x) exp(x) - 1, A * x)); end, toc tic, for i = 1 : 10, E = 1 + full(spfun(@(x) exp(x) - 1, sparse(A * x))); end, toc tic, for i = 1 : 10, F = 1 + spfun(@(x) exp(x) - 1, A * sx); end, toc tic, for i = 1 : 10, G = 1 + spfun(@(x) exp(x) - 1, A * x); end, toc tic, for i = 1 : 10, H = 1 + spfun(@(x) exp(x) - 1, sparse(A * x)); end, toc Elapsed time is 1.490776 seconds. Elapsed time is 2.031305 seconds. Elapsed time is 2.743365 seconds. Elapsed time is 2.818630 seconds. Elapsed time is 2.176082 seconds. Elapsed time is 2.779800 seconds. Elapsed time is 2.900107 seconds.