Ascend-SACT/CBS
模型介绍文件和版本Pull Requests讨论分析
下载使用量0

CBS模型昇腾NPU部署指导

一、模型介绍

1.1 模型概述

CBS(Convergent Born Series,收敛玻恩级数)是面向频域声学亥姆霍兹方程求解设计的数值迭代求解器,作为地震波全波形反演(FWI)任务中的经典基线模型,核心落地场景为地震波频域模拟 —— 作为油气资源勘探、地下介质声学特性成像的核心数值工具,CBS 旨在替代传统频域亥姆霍兹方程求解方法(如 LU 分解、传统玻恩级数),解决其边界反射干扰大、迭代易发散、谱精度难以保证的行业痛点;同时,其反演效果常作为基准参照,用于对比评估 DPOT、FFNO 等新型神经算子模型在地震波全波形反演任务中的精度和性能表现。

1.2 核心模块说明

基于提供的源码,DPOT模型核心模块包括:

模块名功能说明
MixedDSTDFTn正向混合频域变换模块,针对自由表面边界条件,实现 z 方向 DST 与其他方向 DFT 的混合变换,满足应力零边界约束
MixedIDSTDFTn混合逆频域变换模块,完成 MixedDSTDFTn 的逆运算,实现频域结果向空间域的精准映射
CBSBlock迭代计算基础块,整合散射势计算(op_v)、格林函数卷积(op_g)核心算子,实现单步 CBS / 传统玻恩迭代
CBS求解器主类,整合 PML 构建、波数计算、迭代控制、误差评估、PML 移除全流程,对外提供统一求解接口

1.3 关键特性

  • 支持 2D/3D 空间数据处理,适配频域声学亥姆霍兹方程的多维度求解场景,满足地震波全波形反演对不同维度地下介质建模的需求;
  • 融合 PML(完美匹配层)与自由表面两种边界条件,可灵活适配不同地下介质边界场景,保障反演结果的准确性;
  • 采用谱精度频域变换(DFT/DST)实现微分项近似,兼顾迭代收敛性与数值求解精度,为 DPOT、FFNO 等模型提供可靠的性能对比基准;
  • 支持迭代稳定项(epsilon)自适应计算,可在 CBS(收敛玻恩级数)与传统 BS(玻恩级数)模式间灵活切换,解决传统玻恩迭代发散问题,确保基线结果的稳定性与可比性。

二、部署环境

2.1 关键组件信息

项目规格参数
计算卡Ascend 910B3
驱动固件25.2.0
CANN 版本8.5.0
操作系统openEuler 22.03
架构aarch64
MindSpore2.8.0
MindSpeedMindSpeed-LLM master
Megatroncore_v0.12.1
Python3.10.19
torch2.7.1
torch_npu2.7.1.post2

2.2 安装驱动固件

请根据系统和硬件产品型号选择对应版本的社区版本或商用版本的驱动与固件。 参考如下命令安装:

chmod +x Ascend-hdk-<chip_type>-npu-driver_<version>_linux-<arch>.run
chmod +x Ascend-hdk-<chip_type>-npu-firmware_<version>.run
./Ascend-hdk-<chip_type>-npu-driver_<version>_linux-<arch>.run --full --force
./Ascend-hdk-<chip_type>-npu-firmware_<version>.run --full

2.3 安装CANN

获取CANN,安装配套版本的Toolkit、ops和NNAL并配置CANN环境变量,具体请参考CANN软件安装指南

#基于PyTorch框架设置环境变量
source /usr/local/Ascend/cann/set_env.sh # 修改为实际安装的Toolkit包路径
source /usr/local/Ascend/nnal/atb/set_env.sh # 修改为实际安装的nnal包路径

2.4 安装Pytorch及torch_npu

# 安装torch和torch_npu构建参考 https://gitcode.com/ascend/pytorch/releases
pip3 install torch-2.7.1-cp310-cp310-manylinux_2_28_aarch64.whl 
pip3 install torch_npu-2.7.1rc1-cp310-cp310-manylinux_2_28_aarch64.whl

2.5 安装MindSpore

pip install mindspore==2.8.0 -i https://repo.mindspore.cn/pypi/simple --trusted-host repo.mindspore.cn --extra-index-url https://repo.huaweicloud.com/repository/pypi/simple

2.6 安装MindSpeed LLM

安装MindSpeed加速库

git clone https://gitcode.com/ascend/MindSpeed.git
cd MindSpeed
git checkout master  # checkout commit from MindSpeed master
pip3 install -r requirements.txt 
pip3 install -e .
cd ..

准备MindSpeed LLM及Megatron-LM源码

git clone https://gitcode.com/ascend/MindSpeed-LLM.git 
git clone https://github.com/NVIDIA/Megatron-LM.git  # 从github下载Megatron-LM,请确保网络能访问
cd Megatron-LM
git checkout core_v0.12.1
cp -r megatron ../MindSpeed-LLM/
cd ../MindSpeed-LLM
git checkout master

pip3 install -r requirements.txt  # 安装其余依赖库

三、核心适配点

3.1 框架基础替换

所有网络类继承nn.Cell(MindSpore 核心基类),替代 PyTorch 的nn.Module

# 行15-22:导入昇腾兼容的MindSpore核心模块
import mindspore as ms
from mindspore import Tensor, nn, ops, mint, numpy as mnp, lazy_inline
from mindscience import DFTn, IDFTn, DST, IDST
import mindspore as ms
from mindspore import nn, ops, dtype as mstype, mint
from mindspore.ops import DataType, CustomRegOp, CustomOpBuilder

# 行31/71/109:所有计算单元继承MindSpore的nn.Cell
class MixedDSTDFTn(nn.Cell):
class MixedIDSTDFTn(nn.Cell):
class CBSBlock(nn.Cell):
class CBS(nn.Cell):

3.2 昇腾兼容的张量操作算子

ops.swapdims/mint.transpose/ops.concat等是 MindSpore 封装的昇腾 NPU 硬件级算子,可直接在 NPU 上执行;而 numpy 操作会触发Host 侧计算→NPU 传输的低效流程,完全规避。

# 行50-51:昇腾维度交换算子(替代numpy.swapaxes)
dft_ar = ops.swapdims(dft_ar, 2, -1) 
dft_ai = ops.swapdims(dft_ai, 2, -1)

# 行82-83:昇腾转置算子(替代numpy.transpose)
ur = mint.transpose(ur, -2, -1)
ui = mint.transpose(ui, -2, -1)

# 行343:昇腾concat算子(替代numpy.concatenate)
return ops.concat((left, original, right))

3.3 昇腾图模式兼容的条件分支与控制流

# 行156-157:ops.select替代原生if-else(昇腾图模式兼容的条件分支)
dur = ops.select(cond, -vgi / (eps + 1e-8), gvr - ur) 
dui = ops.select(cond, vgr / (eps + 1e-8), gvi - ui)

# 行413:construct内的for循环(MindSpore昇腾图模式支持的循环规范)
for _ in range(self.n_iter):
    dur, dui = self.cbs_block(ur, ui, vr, vi, gr, gi, rhs, eps)
    ur = ur + dur
    ui = ui + dui
    errs = self.compute_error(dur, dui, ur, ui)
    errs_list.append(errs)

3.4 昇腾兼容的复数张量处理(拆分实虚部)

# 行138-150:复数张量拆分为实虚部单独计算(昇腾兼容)
if ops.is_complex(f_star):
    f_star_real = get_real(f_star)
    f_star_imag = get_imag(f_star)
    c_star_squared = c_star**2
    rhs_real = f_star_real / c_star_squared
    rhs_imag = f_star_imag / c_star_squared
    rhs_real_padded = ops.pad(rhs_real, self.pml_size_xyz)
    rhs_imag_padded = ops.pad(rhs_imag, self.pml_size_xyz)
    rhs = make_complex(rhs_real_padded, rhs_imag_padded)
else:
    rhs = mint.nn.functional.pad(f_star / c_star**2, self.pml_size_xyz)

# 行124-130:op_v/op_g算子均拆分实虚部计算,无直接复数操作
def op_v(self, ur, ui, vr, vi):
    wr = ur * vr - ui * vi
    wi = ur * vi + ui * vr
    return wr, wi
def op_g(self, ur, ui, gr, gi):
    fur, fui = self.dft_cell(ur, ui)
    gur = gr * fur - gi * fui
    gui = gi * fur + gr * fui
    wr, wi = self.idft_cell(gur, gui)
    return wr, wi

四、启动推理

4.1 推理主脚本

"""
CBS 算法推理主脚本
功能:基于给定的速度场和源项,求解频域声波方程的波场(实部/虚部)
适配:2D 场景(3D 可修改 shape/dxs 等参数扩展)
"""
import os
import numpy as np
import mindspore as ms
import matplotlib.pyplot as plt
from cbs import CBS

# ====================== 1. 环境配置 ======================
ms.set_context(mode=ms.GRAPH_MODE, device_target="Ascend") 
ms.set_seed(42)  # 固定随机种子
save_dir = "./cbs_inference_results"
os.makedirs(save_dir, exist_ok=True)

# ====================== 2. 推理参数配置 ======================
# 2D 空间网格形状 (nz, nx),3D 改为 (nz, ny, nx)
shape = (128, 128)
# 网格步长 (dz, dx),3D 改为 (dz, dy, dx)
dxs = (0.01, 0.01)
# 迭代配置
n_iter_per_call = 20  # 单次 construct 调用的迭代次数
tol = 1e-3            # 收敛误差阈值
max_iter = 10000      # 最大迭代次数
# 边界配置
btype = "pml"         # 边界类型:pml / freesurface
pml_size = 16         # PML 层厚度
alpha = 1.0           # PML 衰减强度
rampup = 12           # PML 过渡平滑度
remove_pml = True     # 输出是否移除 PML 层

# ====================== 3. 生成测试数据(速度场 + 源项) ======================
batch_size = 1  # 批次大小
channel = 1     # 通道数

# 3.1 速度场 c_star (非维度化,物理含义:介质波速)
# 构造分层速度场(示例):上层低速,下层高速
c_star = np.ones((batch_size, channel) + shape, dtype=np.float32) * 1.5
z_split = shape[0] // 2
c_star[:, :, z_split:, :] = 2.5  # 下半部分速度更高

# 3.2 源项 f_star (源位置掩码,仅源点位置为1,其余为0)
f_star = np.zeros((batch_size, channel) + shape, dtype=np.float32)
# 源点位置:网格中心
src_z, src_x = shape[0] // 2, shape[1] // 2
f_star[:, :, src_z, src_x] = 1.0  # 点源

# 转换为 MindSpore Tensor
c_star = ms.Tensor(c_star, dtype=ms.float32)
f_star = ms.Tensor(f_star, dtype=ms.float32)

# ====================== 4. 初始化 CBS 求解器 ======================
cbs_solver = CBS(
    shape=shape,
    dxs=dxs,
    n_iter=n_iter_per_call,
    pml_size=pml_size,
    alpha=alpha,
    rampup=rampup,
    btype=btype,
    remove_pml=False,  # 迭代过程中保留 PML,最终输出再移除
    epsilon=None       # 自动计算稳定系数
)

# ====================== 5. 执行推理(求解波场) ======================
print("开始 CBS 推理求解...")
# 初始波场设为 0(ur_init/ui_init=None 时自动初始化为 0)
ur, ui, errs_list = cbs_solver.solve(
    c_star=c_star,
    f_star=f_star,
    tol=tol,
    max_iter=max_iter,
    remove_pml=remove_pml,
    print_info=True
)

# ====================== 6. 结果分析与可视化 ======================
# 6.1 迭代误差分析
errs_np = [err.asnumpy() for err in errs_list]
errs_max = [np.max(err) for err in errs_np]
errs_mean = [np.mean(err) for err in errs_np]

# 绘制迭代误差曲线
plt.figure(figsize=(10, 4))
plt.subplot(1, 2, 1)
plt.plot(errs_max, label="Max Error")
plt.plot(errs_mean, label="Mean Error")
plt.xlabel(f"Iteration Step (×{n_iter_per_call})")
plt.ylabel("Relative Error")
plt.yscale("log")
plt.title("迭代误差变化")
plt.legend()
plt.grid(True, alpha=0.3)

# 6.2 波场可视化(实部 + 虚部)
ur_np = ur.asnumpy()[0, 0]  # 取 batch=0, channel=0 的 2D 波场实部
ui_np = ui.asnumpy()[0, 0]  # 取 batch=0, channel=0 的 2D 波场虚部

plt.subplot(1, 2, 2)
plt.imshow(ur_np, cmap="seismic", aspect="auto")
plt.colorbar(label="波场实部")
plt.title("波场实部分布")
plt.xlabel("X 网格")
plt.ylabel("Z 网格")

plt.tight_layout()
plt.savefig(os.path.join(save_dir, "cbs_wavefield_real.png"), dpi=300, bbox_inches="tight")

# 绘制虚部分布
plt.figure(figsize=(8, 6))
plt.imshow(ui_np, cmap="seismic", aspect="auto")
plt.colorbar(label="波场虚部")
plt.title("波场虚部分布")
plt.xlabel("X 网格")
plt.ylabel("Z 网格")
plt.savefig(os.path.join(save_dir, "cbs_wavefield_imag.png"), dpi=300, bbox_inches="tight")

# ====================== 7. 结果保存 ======================
# 保存波场数据(实部/虚部)
np.save(os.path.join(save_dir, "wavefield_real.npy"), ur_np)
np.save(os.path.join(save_dir, "wavefield_imag.npy"), ui_np)
# 保存迭代误差
np.save(os.path.join(save_dir, "iteration_errors.npy"), errs_np)

print(f"推理完成!结果已保存至 {save_dir}")
print(f"波场形状(移除 PML 后):{ur_np.shape}")
print(f"最终迭代最大误差:{errs_max[-1]:.6f}")
print(f"最终迭代平均误差:{errs_mean[-1]:.6f}")