我需要f(x)=exp(A*x)
反复计算一个微小的可变列向量x
和一个巨大的常量矩阵A
(多行,几列)。换句话说,x
很少,但A*x
很多。我的问题维度是这样的,它A*x
需要与 exp() 部分一样多的运行时间。
除了泰勒展开和预先计算一系列值exp(y)
(假设已知 的y
值范围A*x
),相对于 MATLAB 自己所做的事情,我还没有设法显着加快(同时保持准确性),我是考虑分析重述问题,以便能够预先计算一些值。
例如,我发现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
这将允许我预先计算exp(A)
一次,但循环中所需的求幂与原始函数调用一样昂贵exp()
,并且必须另外执行乘法 (\prod)。
有没有我可以遵循的其他想法,或者我可能错过的 MATLAB 中的解决方案?
编辑:更多细节
A
是 26873856 x 81 的大小(是的,它是那么大),所以x
是 81 x 1。
nnz(A) / numel(A)
是0.0012
,nnz(A*x) / numel(A*x)
是0.0075
。我已经使用稀疏矩阵来表示A
,但是,稀疏矩阵的 exp() 不再是稀疏的。所以事实上,我存储x
non-sparse 并且我计算exp(full(A*x))
结果是快/慢full(exp(A*x))
(我认为A*x
无论如何都是非稀疏的,因为 x 是非稀疏的。)exp(full(A*sparse(x)))
是一种拥有 sparse 的方法A*x
,但速度较慢. 甚至更慢的变体是exp(A*sparse(x))
(对于稀疏类型的非稀疏矩阵具有双倍的内存影响)和full(exp(A*sparse(x))
(这再次产生非稀疏结果)。
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.
是的,我确实计算了元素 exp,我更新了上面的等式以反映这一点。
另一个编辑:我试图变得聪明,但收效甚微:
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.