Performance MATLAB中加速exp(A*x)的解析方法

Performance MATLAB中加速exp(A*x)的解析方法,performance,matlab,simplify,exp,Performance,Matlab,Simplify,Exp,我需要为一个微小的可变列向量x和一个巨大的常量矩阵A(多行,少列)重复计算f(x)=exp(A*x)。换句话说,x很少,但是A*x很多。我的问题维度是这样的:A*x占用的运行时间与exp()部分差不多 除了泰勒展开和预先计算值的范围exp(y)(假设已知a*x的值的范围y),相对于MATLAB本身的工作,我还没有设法大大加快速度(同时保持准确性),我正在考虑重新分析这个问题,以便能够预先计算一些值 例如,我发现exp(A*x)\u I=exp(\sum\u j A\u ij x\u j)=\pr

我需要为一个微小的可变列向量
x
和一个巨大的常量矩阵
A
(多行,少列)重复计算
f(x)=exp(A*x)
。换句话说,
x
很少,但是
A*x
很多。我的问题维度是这样的:
A*x
占用的运行时间与exp()部分差不多

除了泰勒展开和预先计算值的范围
exp(y)
(假设已知
a*x
的值的范围
y
),相对于MATLAB本身的工作,我还没有设法大大加快速度(同时保持准确性),我正在考虑重新分析这个问题,以便能够预先计算一些值

例如,我发现
exp(A*x)\u I=exp(\sum\u j A\u ij x\u j)=\prod\u j exp(A\u ij x\u j)=\prod\u j exp(A\u ij)^x\u j

这将允许我预先计算
exp(A)
一次,但是循环中所需的求幂与原始
exp()
函数调用一样昂贵,并且必须另外执行乘法(\prod)

有没有其他我可以遵循的想法,或者MATLAB中我可能错过的解决方案

编辑:更多详细信息

A
的尺寸是26873856乘以81(是的,它太大了),所以
x
的尺寸是81乘以1。
nnz(A)/numel(A)
is
0.0012
nnz(A*x)/numel(A*x)
is
0.0075
。我已经使用稀疏矩阵来表示
a
,但是,稀疏矩阵的exp()不再是稀疏的。所以事实上,我存储了
x
非稀疏,我计算了
exp(full(A*x))
,结果它和
full(exp(A*x))
(我认为
A*x
是非稀疏的,因为x是非稀疏的。)
exp(full(A*sparse(x))
是一种拥有稀疏
A*x
的方法,但速度较慢。更慢的变体是
exp(A*sparse(x))
(对于类型为sparse的非稀疏矩阵,内存影响加倍)和
full(exp(A*sparse(x))
(这同样会产生非稀疏结果)

是的,我会计算元素的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.

计算机并不是真的做指数,你可能会认为他们做了,但他们做的是高精度的多项式近似

参考资料:

最后一个参考资料看起来很不错,也许应该是第一个

由于您正在处理图像,因此可能有离散数量的强度级别(通常为255)。这可以减少采样或查找,具体取决于“A”的性质。检查这一点的一种方法是对具有足够代表性的“x”值组执行以下操作:

如果你能把你的图像分为“更有趣”和“不那么有趣”——就像你在看一张X光照片一样,能把所有“人体外”的位置都剪下来,然后把它们夹在零上,使你的数据变得稀疏,你就可以减少唯一值的数量。数据中的“模式”

我的方法包括:

  • 看看exp(x)的替代公式,它们精度较低,但速度较快
  • 如果“x”的级别足够少,请考虑表格查找
  • 如果要进行表格查找,级别“稍微太多”,请考虑将插值和表格查找相结合
  • 考虑一个基于分段模式的单一查找(或替代公式)。如果您知道这是一块骨头,并且正在查找一条静脉,那么可能应用的数据处理成本应该更低
现在我不得不问自己,为什么你会生活在exp(A*x)*x的如此多的迭代中,我想你可能会在频率/波数域和时间/空间域之间来回切换。你也可能会以exp(x)为基础处理概率,并做一些贝氏乐趣。我不知道exp(x)是一个很好的共轭先验,所以我将使用傅里叶材料

其他选择: -考虑使用FFT、FFT2或FFTN给你的矩阵——它们是快速的,并且可以做你寻找的一部分。 我确信在以下方面存在更大的变化:

你可能可以将查找与使用woodbury矩阵的计算混合在一起。我必须考虑一些以确保。()在某一点上,我知道所有重要的事情(CFD、FEA、FFT)都与矩阵求逆有关,但我已经忘记了具体的细节

现在,如果你生活在MatLab,那么你可以考虑使用“编码器”将MATLAB代码转换成C代码。不管译员有多有趣,一个好的C编译器都会快很多。这里显示了我所使用的语言:从13:49开始。它非常简单,但它显示了规范解释语言(python)和编译版本(cython/c)之间的区别

我相信,如果我有更多的细节,并被要求,那么我可以更积极地参与一个更具体相关的答案

你可能没有一种在传统硬件上做这件事的好方法,你可能会考虑GPGPU之类的东西。CUDA和它的对等体有大量的并行操作,可以让一些视频卡的成本大幅度提高。你可以拥有成千上万个“核心”(过度美化的管道)。做一些ALU的工作,如果工作是适当的并行化(就像这个样子),那么它可以更快地完成

编辑:

我正在考虑。如果我有一些“大铁”来开发而不是生产,我会考虑使用他们的Eurqa Pro。
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.
y=Ax
cdfplot(y(:))