MATLAB和R之间的执行时间差异很大

Haf*_*fez 3 performance matlab r numerical-methods runge-kutta

我想实现一个非常简单的4 阶龙格库塔方法,解决ODE y'=f(x,y).

我已经在R和MATLAB中实现了算法(见下文),但由于某种原因,在MATLAB中运行需要几分钟,在R中运行几毫秒.

我的问题是为什么?

似乎唯一的区别是初始化,并且玩这个似乎没有什么区别.


R脚本:

# Initialise Variables ----------------------------------------------------

L  = 1 #Domain of solution function
h  = 0.01#step size
x0 = 0
y0 = 0
x  = x0
y  = y0

# Define Forcing Function -------------------------------------------------

force = function(x,y){
  -16*y + 15*exp(-x)
}


# Compute Algorithm -------------------------------------------------------

for(i in 0:(L/h)){

  k1 = h*force(x,y[i])
  k2 = h*force(x + h/2, y[i] + k1 /2)
  k3 = h*force(x + h/2, y[i] + k2 /2)
  k4 = h*force(x + h  , y[i] + k3   )

  temp=y[i] + (1/6)*(k1 + 2*k2 + 2*k3 + k4)

  y = c(y,temp)
  x = x + h
  i = i+1  
}

t <- seq(from=0, to=L, by=h)
plot(t,y,type="l")
Run Code Online (Sandbox Code Playgroud)

MATLAB脚本:

%% Initialise Variables
y0 = 0;
x0 = 0;
L  = 1; %Length of Domain of function (here y)
N  = 100; %Number of steps to break the domain into
h  = L/N; %Step Size

yi = y0; %intermediate value of y
xi = x0; %intermediate value of x to be ticked in algo

y = zeros(N,1); %store y values as components
x = 0:h:L; %just for plot later

%% Define Forcing Function
syms f(A,B)
f(A,B) = 15*exp(-A) - 16*B;

%% Execute Algorithm
for n = 1:1:N;
    xi= h*(n-1);

    k1= h*f(xi,yi);    
    k2= h*f(xi + h/2 , yi + k1/2);
    k3= h*f(xi + h/2 , yi + k2/2);
    k4= h*f(xi + h   , yi + k3  );

    yi= yi + (1/6)*(k1 + 2*k2 + 2*k3 + k4);
    y(n,1)=yi;
end

%plot(x,y)
Run Code Online (Sandbox Code Playgroud)

Dev*_*-iL 9

您遇到此问题的原因是因为您使用符号变量来进行纯数字计算.

如果您定义f如下:

f = @(A,B)15*exp(-A) - 16*B;
Run Code Online (Sandbox Code Playgroud)

循环几乎立即完成.几个笔记:

  • 上述的语法是用来定义一个函数句柄匿名函数.
  • 结果xy向量具有不同的长度,因此您之后将无法使用plot它们.
  • 将来您应该使用profile代码来查找性能瓶颈.

PS
MAT中与R函数定义相当的MATLAB非常相似:

function out = force(x)
  out = 15*exp( -x(1) ) - 16*x(2);
end
Run Code Online (Sandbox Code Playgroud)

要么

function out = force(x,y)
  out = 15*exp(-x) - 16*y;
end
Run Code Online (Sandbox Code Playgroud)

...取决于输入是否作为向量.