You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多轨迹随机数值积分效率优化:欧拉-马尔可夫方法并行与Numba适配

随机微分方程Euler-Maruyama数值求解的效率优化问题

问题背景

我用Euler-Maruyama方法实现随机微分方程(SDE)的数值求解,现有代码能正常运行但效率极低。因为问题本身带随机性,需要计算大量独立轨迹,目前是逐个求解的方式。尝试直接去掉轨迹循环改成向量化形式但未生效,用Numba优化求解器也失败了。

现有可运行但低效的代码:

%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
import time
from numba import jit, njit
import os

def A(u):
    x=u[0]
    y=u[1]
    z=u[2]
    
    omega=1/2*np.sqrt((1+8*kappa*z*z))  
    
    
    A=np.array([[-2,omega,0],
                [-omega,0,0],
                [0,0,-kappa]])

    
    du=A.dot(u)
    return du


def B(u,w):
    x=u[0]
    y=u[1]
    z=u[2]
    
    g=np.sqrt(kappa*nth)

    B=np.array([[0],
                [1],
                [1]])*g
    
    return np.reshape(B*w,len(u0))


def SDE(A,B):
    u = np.zeros((len(u0),Nmax+1,Mmax),dtype=np.complex64)
    for m in range(Mmax):
        u[:,0,m]=u0
        for n in range(0,Nmax):
            u[:,n+1,m] = u[:,n,m]+dt*A(u[:,n,m])+B(u[:,n,m],w[n,m])*np.sqrt(dt)   
            
    return u


#Parameters
kappa=0.05
nth=1.
gamma=1

Mmax=100 #number of trajectories

Tmax=10. ##max value for time
dt=0.05
Nmax=int(Tmax/dt) ##number of steps

t_list=np.arange(0,Tmax+dt/2,dt)


w = np.random.randn(Nmax+1,Mmax)

u0 = np.array([1., 0., np.sqrt(nth)/2])

u_t=SDE(A,B)

u_mean=np.mean(u_t,axis=2)

实际系统维度更大、轨迹数量更多,期望的高效求解器形式(目前无法正常运行):

def SDE(A,B):
    u = np.zeros((len(u0),Nmax+1,Mmax),dtype=np.complex64)
    u[:,0,:]=u0
    for n in range(0,Nmax):
       u[:,n+1,:] = u[:,n,:]+dt*A(u[:,n,:])+B(u[:,n,:],w[n,:])*np.sqrt(dt)   
            
    return u

解决方案

1. 核心问题:A/B函数不支持批量计算

原代码中A、B函数仅处理单个轨迹的1维向量输入,无法适配向量化所需的(维度, 轨迹数)批量输入,这是直接去循环失败的根本原因。需先修改这两个函数支持批量计算:

修改后的A函数

def A(u):
    # u形状: (3, Mmax)
    x = u[0, :]
    y = u[1, :]
    z = u[2, :]
    
    omega = 0.5 * np.sqrt(1 + 8 * kappa * z**2)
    
    # 构造批量系数矩阵,形状: (3, 3, Mmax)
    A_mat = np.zeros((3, 3, u.shape[1]), dtype=np.complex64)
    A_mat[0, 0, :] = -2
    A_mat[0, 1, :] = omega
    A_mat[1, 0, :] = -omega
    A_mat[2, 2, :] = -kappa
    
    # 批量矩阵-向量乘法,结果形状: (3, Mmax)
    du = np.einsum('ijk,jk->ik', A_mat, u)
    return du

修改后的B函数

def B(u, w):
    # u形状: (3, Mmax), w形状: (Mmax,)
    g = np.sqrt(kappa * nth)
    
    # 构造批量噪声向量,形状: (3, Mmax)
    B_vec = np.zeros_like(u)
    B_vec[1, :] = g * w
    B_vec[2, :] = g * w
    return B_vec

2. 向量化SDE主函数

现在可以直接使用你期望的无轨迹循环形式,注意扩展初始向量维度以匹配批量输入:

def SDE(A, B):
    u = np.zeros((len(u0), Nmax+1, Mmax), dtype=np.complex64)
    u[:, 0, :] = u0[:, np.newaxis]  # 把u0从(3,)扩展为(3,1),适配轨迹维度
    for n in range(Nmax):
        u[:, n+1, :] = u[:, n, :] + dt * A(u[:, n, :]) + B(u[:, n, :], w[n, :]) * np.sqrt(dt)
    return u

3. Numba优化(针对超大规模场景)

若向量化后效率仍不足,用Numba的njit装饰器编译优化,注意遵循Numba的数组操作规则:

from numba import njit, prange

@njit(parallel=True)
def A_numba(u, kappa):
    # u形状: (3, Mmax)
    x = u[0, :]
    y = u[1, :]
    z = u[2, :]
    du = np.zeros_like(u)
    
    for m in prange(u.shape[1]):
        omega = 0.5 * np.sqrt(1 + 8 * kappa * z[m]**2)
        du[0, m] = -2 * x[m] + omega * y[m]
        du[1, m] = -omega * x[m]
        du[2, m] = -kappa * z[m]
    return du

@njit(parallel=True)
def B_numba(w, kappa, nth):
    # w形状: (Mmax,)
    g = np.sqrt(kappa * nth)
    B_vec = np.zeros((3, w.shape[0]), dtype=np.complex64)
    B_vec[1, :] = g * w
    B_vec[2, :] = g * w
    return B_vec

@njit(parallel=True)
def SDE_numba(u0, dt, sqrt_dt, Nmax, Mmax, w, kappa, nth):
    u = np.zeros((u0.shape[0], Nmax+1, Mmax), dtype=np.complex64)
    u[:, 0, :] = u0[:, np.newaxis]
    
    for n in range(Nmax):
        current_u = u[:, n, :]
        u[:, n+1, :] = current_u + dt * A_numba(current_u, kappa) + B_numba(w[n, :], kappa, nth) * sqrt_dt
    return u

调用Numba版本代码

# 预计算sqrt_dt避免循环内重复计算
sqrt_dt = np.sqrt(dt)

# 调用优化后的求解器
u_t = SDE_numba(u0, dt, sqrt_dt, Nmax, Mmax, w, kappa, nth)

4. 额外优化建议

  • 预计算所有常数(如sqrt_dt、g),避免在循环/函数内重复计算
  • 超大规模轨迹场景可结合multiprocessing做轨迹分块并行,但Numba的parallel=True已能覆盖多数场景
  • 避免在循环内创建新数组,尽量复用内存

内容的提问来源于stack exchange,提问作者J.Agusti

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 02:24:52