我是两个月前的Matlab初学者。我将它用于夏季项目来处理MRI图像。 最近,我为下面的集成编写了代码。但是,这两种方法都非常慢。运行它们花了一天时间。如何改进它们以缩短运行时间?
符号方法:
syms t;
T=t*ones(79,95,78);
RF1=(1/2)*double(int(((T+x1).^(-1/2)).*((T+y1).^(-1/2)).*((T+z).^(-1/2)),t,0,inf));
RD1=(3/2)*double(int(((T+x1).^(-1/2)).*((T+y1).^(-1/2)).*((T+z).^(-3/2)),t,0,inf));
数字方法:
fun1=@(T) ((T+x1).^(-1/2)).*((T+y1).^(-1/2)).*((T+z).^(-1/2));
RF1=(1/2)*integral(fun1,0,inf,'ArrayValued',true);
fun2=@(T) ((T+x1).^(-1/2)).*((T+y1).^(-1/2)).*((T+z).^(-3/2));
RD1=(3/2)*integral(fun2,0,inf,'ArrayValued',true);
x1
,y1
,z
是79 x 95-by-78真实矩阵。
答案 0 :(得分:6)
您正在尝试计算555,750个积分,因此需要一些时间。以下是一些可能有用的建议。
<强> 1 强> 首先,您可以稍微更有效地表达方程式(这可能会影响结果的数值精度,具体取决于值的大小和问题的稳定性):
fun1 = @(T)1./sqrt((T+x1).*(T+y1).*(T+z));
fun2 = @(T)1./sqrt((T+x1).*(T+y1).*(T+z).*(T+z).*(T+z));
可以对符号情况执行相同的转换。在仅使用较小(4,524个元素阵列)x1
,y1
和z
数组的随机值的测试中,我的计算机上的两组积分计算速度都快了四倍。
<强> 2 强> 通过将匿名函数转换为常规M-File函数,您也可以略微提高速度。在单独的文件中:
function RF1 = fun1(T,x1,y1,z)
RF1 = 1./sqrt((T+x1).*(T+y1).*(T+z));
和
function RD1 = fun2(T,x1,y1,z)
RD1 = 1./sqrt((T+x1).*(T+y1).*(T+z).*(T+z).*(T+z));
然后打电话给他们传递x1
,y1
和z
作为参数:
RF1 = 0.5*integral(@(T)fun1(T,x1,x2,z),0,Inf,'ArrayValued',true);
RD1 = 1.5*integral(@(T)fun2(T,x1,x2,z),0,Inf,'ArrayValued',true);
我在机器上看到一个小但不可忽略的差异:我尝试的数据快了大约10%。这可能是由于M-File是单独编译的JIT,因为常规函数的处理方式可能与匿名函数略有不同。
第3 强>
当然,您还应该使用integral
的绝对和相对容差。您还可以查看矢量化quadv
是否更快并提供准确结果(请注意,此函数将在未来版本的Matlab中删除)。根据数据的性质和功能,甚至可以将问题离散化(使用较大的值而不是Inf
)并使用trapz
之类的方法来执行整合,虽然我不知道这是否会更快。
对于符号案例,您可以尝试将t
定义为真实(即syms t real;
),并可能将'IgnoreAnalyticConstraints'
选项指定为true
,以查看其中任何一个提高速度。符号数学也可能对内存效率低下,因此您也可以尝试分解问题并集成块(例如逐行)。除int
之外还有其他选项可能更快,但如果没有您的实际数据值,则很难说(如果您不需要精确度,纯数字方法会快得多)。
<强> 4 强> 最后,如果您不需要太多精确度,只关心速度,则可以在C "fast inverse square root trick"中实施mex。