news 2026/10/14 3:14:45

AscendNPU-IR 入门指南:基于 MLIR 的昇腾亲和算子编译中间表示

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
AscendNPU-IR 入门指南:基于 MLIR 的昇腾亲和算子编译中间表示
  • 编译器
  • 人工智能
  • Ascend
  • CANN

【免费下载链接】AscendNPU-IR

AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优

项目地址:https://gitcode.com/Ascend/AscendNPU-IR
点击查看免费下载

AscendNPU-IR(AscendNPU Intermediate Representation,简称 AscendNPU IR)是基于 MLIR 生态构建的面向昇腾 AI 处理器的编译中间表示,通过 HFusion、HIVM、HACC 等多级自研方言提供从高层语义到底层指令的完备表达与逐层优化能力。本文以仓库根目录README_zh.md为主线,结合仓库源码与配套文档,系统介绍其定位、仓库结构、核心编译流程、构建安装方式与首个端到端算子示例,帮助读者快速建立对该项目整体轮廓的认知,并掌握源码构建、测试验证与上板执行的完整路径。

AscendNPU IR 在 CANN 软件栈中的定位

项目定位:面向昇腾的统一编译接入层

AscendNPU IR 是基于 MLIR 构建的、面向昇腾亲和算子编译时使用的中间表示,核心目标是提供昇腾完备表达能力,并通过编译优化提升昇腾 AI 处理器计算效率,支持通过生态框架使能昇腾 AI 处理器与深度调优。

从抽象层级看,AscendNPU IR 提供两方面的接口能力(对应 项目介绍):

  • 多级高层抽象接口:屏蔽昇腾计算、搬运、同步指令细节,编译优化自动感知硬件架构,将硬件无关表达映射到底层指令,提升算子开发易用性;
  • 细粒度性能控制接口:允许精准控制片上内存地址、流水同步插入位置、是否使能乒乓流水优化等,为性能调优留出细粒度控制空间。

在生态层面,AscendNPU IR 通过开源社区开放接口,支持生态框架灵活对接,高效使能昇腾 AI 处理器。按照 架构设计文档 的表述,它会自下而上对昇腾硬件底层指令、核内资源、核间资源、SOC 资源逐层抽象编译优化,多层抽象间分层解耦、开源开放,作为生态框架面向昇腾的统一编译接入层。

AscendNPU IR 逻辑架构图

核心方言:HFusion / HIVM / HACC 的分层协作

AscendNPU IR 自研设计有 HFusion、HIVM、HACC、Annotation、Scope 五种方言,分别承担不同抽象层级的职责(详见 架构设计):

方言职责关键能力
HFusion(Hybrid Fusion)硬件相对无关的优化与生态对接基于 MLIR 社区 Linalg 方言的扩展集,处理named operations以最大化保留高层语义;支持与 Arith、Math、Torch 等方言的 Conversion 对接,完成 Tensor 表达式化简、BF16/Bool数据类型合法化等预处理,并自动融合生成 Device Kernel 算子及 Host Tiling 函数
HIVM(Hybrid ISA Virtual Machine)感知 NPU 硬件细节,将高层语言转换为底层指令对计算、搬运、同步进行 Tile 级抽象,屏蔽底层指令参数;负责 CV 核映射(Mix Kernel 的 CV 融合、核间同步、CVPipeline 流水与 AutoSubTiling 等)、核内片上内存映射与多级流水/指令映射
HACC异构硬件抽象表达 Host/Device 编程模型与 launch 语义
Annotation / Scope编译提示与作用域标记对特定 Operand 或 Operation 标记compiler hint信息

从代码结构看(对应 include/bishengir/Dialect 目录),这些自研方言与社区方言(Arith、Math、MemRef、SCF、Tensor 等)的扩展增强并行存在,转换层代码则集中在 lib/Conversion 下,例如 TorchToHFusion、HFusionToHIVM、HIVMToLLVM 等。

关键编译特性

结合 简介 与 架构设计,AscendNPU IR 的编译优化可归纳为以下核心能力:

  • CV 融合与流水:感知 NPU CV 核分离硬件架构,自动对同时包含 cube 与 vector 操作的 Mix Kernel 进行 CV 融合编译,通过 CVPipeline pass 调整 Cube/Vector 代码顺序保证 CV 核流水并行,通过 AutoSubTiling 实现 CV 配比 1:2 切分;
  • 自动内存规划与流水同步:PlanMemory 自动完成片上内存空间推导、数据格式推导、访存自动对齐与地址分配,AutoSync 自动插入流水同步操作;
  • 块化与调度:AutoBlockify、AutoFlatten、AutoSchedule 等 pass 在保持高层语义的前提下获得可移植性能;
  • 生态对接:支持与 PyTorch(Torch-MLIR)、TileLang、Triton 等框架对接。

此外,在 Ascend 950PR&950DT 系列产品上,HIVM 方言还提供 SIMT 编译支持,将社区 TritonGPU 方言对接至 HIVM,支持纯 SIMD、纯 SIMT 及 SIMD/SIMT 混合编译模式(详见 架构设计中的 Ascend 950 特性章节)。

仓库结构:bishengir 源码目录与文档工程

README_zh.md给出了仓库关键目录的鸟瞰(当前仓库实际结构与之一致,并多了triton/、unittests/等目录):

├── bishengir // 源码目录 │ ├── cmake │ ├── include // 头文件(.h/.hpp)与 TableGen 定义(.td) │ ├── lib // 源文件(.cpp),目录结构与 include 保持一致 │ ├── test // 测试用例(.mlir lit 测试) │ │ └── Integration // 端到端用例 │ └── tools // 二进制工具(bishengir-compile、bishengir-opt 等) ├── build-tools // 构建工具(build.sh 一键构建脚本) ├── docs // Sphinx 文档工程(英文 docs/source/en、中文 docs/source/zh_cn) ├── third-party // 三方依赖(llvm-project、torch-mlir、shmem) ├── CMakeLists.txt ├── LICENSE ├── NOTICE ├── README.md // 英文版 README └── README_zh.md // 中文版 README(本文主线)

需要说明的是,README_zh.md中的仓库结构图标注了build-tools目录,但当前仓库中该目录实际存放于 build-tools(含 build.sh 等脚本);third-party下则包含 llvm-project、torch-mlir、shmem 三个三方子模块。

代码组织方式:非侵入式扩展社区

AscendNPU IR 对 MLIR 社区的增强采用优先独立目录扩展的策略:先在include/bishengir/Dialect下创建对应方言目录并新增文件来扩展能力,避免对社区侵入式修改;无法隔离的修改则直接提交到third-party下对应的 Ascend 维护分支(如 llvm-project 对应Ascend/AscendNPU-IR/llvmorg-19.1.7、torch-mlir 对应Ascend/AscendNPU-IR/main-20250716),每个修改均有单独 commit 信息便于回合社区。历史版本中通过build-tools/patches目录 patch 文件在构建时应用的方式已废弃。

IR 主要由Conversion、Dialect、tools三部分组成:Conversion承载不同方言间转换能力(既包括 TorchToHFusion 等生态对接转换,也包括 HFusionToHIVM 等内部方言间转换),Dialect下是各方言定义与实现,tools下定义编译工具链,其中 bishengir-compile 是 AscendNPU IR 编译器的命令行驱动程序。

编译工具链:bishengir-compile 与 hivmc 的分工

按照 架构设计 中“编译流程”一节的描述,AscendNPU IR 对应工具链分工如下:

  • bishengir-compile:把高抽象层级的 Tile 级 Op 编译成感知 NPU 硬件架构的 low level op,输入和输出均为 MLIR;
  • hivmc:把 low level 的 MLIR 转成 LLVM IR,并基于 LLVM IR 进行底层指令编译优化,最终生成算子二进制。

源码中两个工具分别位于 bishengir/tools/bishengir-compile/bishengir-compile.cpp 与 bishengir/tools/hivmc/hivmc.cpp。

构建安装:三种方式覆盖不同场景

README_zh.md将构建安装指引指向 构建安装指南,该指南提供了完整的环境准备与三种构建方式。

环境依赖准备

编译器与工具链要求:

  • CMake >= 3.28
  • Ninja >= 1.12.0
  • 推荐使用 Clang >= 10 与 LLD >= 10(使用 LLVM LLD 可显著提升构建速度)

源码拉取与子模块初始化(本项目依赖 LLVM、Torch-MLIR 等三方库):

git clone https://gitcode.com/Ascend/ascendnpu-ir.git cd ascendnpu-ir git submodule update --init --recursive

CANN 包安装:端到端运行依赖 CANN 环境。需下载 CANN Toolkit 包及与硬件对应的ops包,安装并配置环境变量:

# 以 x86 系统 Atlas A3 系列产品安装 CANN 包为例,{version} 为 CANN 版本,如 9.0.0 chmod +x Ascend-cann_{version}_linux-x86_64.run chmod +x Ascend-cann-A3-ops_{version}_linux-x86_64.run ./Ascend-cann_{version}_linux-x86_64.run --full [--install-path=${PATH-TO-CANN}] ./Ascend-cann-A3-ops_{version}_linux-x86_64.run --install [--install-path=${PATH-TO-CANN}] # 若是 8.5.0 及更早期版本,路径为 ${PATH-TO-CANN}/ascend-toolkit/set_env.sh source ${PATH-TO-CANN}/cann/set_env.sh

方式一:一键构建脚本 build.sh(推荐)

在项目根目录执行 ./build-tools/build.sh 即可完成配置、构建和安装,脚本会自动处理 CMake 配置、Ninja 编译及安装步骤。主要参数如下:

参数说明默认值
-o,--build PATH构建产物输出目录./build
--build-type TYPE构建类型Release
-r,--rebuild清空构建目录并重新配置关闭
-j,--jobs N并行编译线程数CPU 核心数的 3/4
--install-prefix PATH安装路径BUILD_DIR/install
--c-compiler PATH/--cxx-compiler PATHC / C++ 编译器路径clang / clang++
--llvm-source-dir DIRLLVM 源码目录third-party/llvm-project
--build-test构建并运行测试关闭
-t,--build-bishengir-template构建 BiShengIR 模板库,需 CANN 9.0.0,端到端用例必须启用关闭
--bisheng-compiler PATHbisheng 编译器目录,构建模板库时需指定无
--build-torch-mlir同时构建 torch-mlir关闭
--python-binding启用 MLIR python-binding关闭
--enable-cpu-runner启用 CPU runner关闭
--disable-ccache禁用 ccache启用(若已安装)
--enable-assertion启用断言关闭
--fast-build跳过安装步骤关闭
--add-cmake-options OPTIONS追加 CMake 选项无

常用示例:

# 首次构建(需先初始化子模块) ./build-tools/build.sh -o ./build --build-type Release # Debug 构建并运行测试 ./build-tools/build.sh -o ./build --build-type Debug --build-test # 重新构建并构建模板库(端到端用例执行依赖模板库) ./build-tools/build.sh -r -o ./build --fast-build -t --bisheng-compiler=/usr/Ascend/cann/bin # 如遇构建失败,建议尝试加入 LLD 链接选项 ./build-tools/build.sh -o ./build --add-cmake-options "-DLLVM_ENABLE_LLD=ON -DCMAKE_LINKER=lld"

方式二:手动 CMake + Ninja 构建

适用于需要精细化控制编译参数的场景,前置条件是已完成子模块初始化。核心命令如下(完整参数见 构建安装指南):

mkdir -p build && cd build export LLVM_SOURCE_DIR="$(realpath ../third-party/llvm-project)" cmake ${LLVM_SOURCE_DIR}/llvm -G Ninja \ -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ \ -DCMAKE_BUILD_TYPE=Release \ -DLLVM_ENABLE_PROJECTS="mlir" \ -DLLVM_EXTERNAL_PROJECTS="bishengir" \ -DLLVM_EXTERNAL_BISHENGIR_SOURCE_DIR="$(realpath ..)" \ -DBSPUB_DAVINCI_BISHENGIR=ON -DBISHENG_DAVINCI_BISHENGIR=ON \ -DLLVM_BSPUB_DAVINCI_BISHENGIR_A5=ON -DLLVM_BSPUB_DAVINCI_BISHENGIR_A5_NPUIR=ON \ -DBISHENGIR_ENABLE_PM_CL_OPTIONS=ON -DBISHENGIR_ENABLE_TRITON_COMPILE=ON \ -DLLVM_BSPUB_DAVINCI_BISHENGIR=ON \ -DLLVM_ENABLE_LLD=ON -DCMAKE_LINKER=lld ninja -j32

可选扩展参数还包括:-DCMAKE_INSTALL_PREFIX="${PWD}/install"(安装路径)、-DLLVM_MAJOR_VERSION_21_COMPATIBLE=ON(LLVM 版本 ≥ 21 时添加)、-DLLVM_ENABLE_ASSERTIONS=ON(启用断言)、-DMLIR_ENABLE_BINDINGS_PYTHON=ON(启用 Python binding)、-DLLVM_TARGETS_TO_BUILD="host;Native"(启用 CPU runner)、-DBISHENGIR_BUILD_TEMPLATE=ON -DBISHENG_COMPILER_PATH=...(构建模板库)等。注意:[]表示可选项,使用某选项时去掉行首#和[]再加入命令。

方式三:二进制安装与 Docker 镜像

  • 二进制安装:AscendNPU IR 二进制会随 CANN Toolkit 包一起安装,无需自行编译;
  • Docker 镜像:可以直接复用 CANN 镜像,也可参考 docker 目录下不同架构的 Dockerfile 构建本地镜像。x86_64 镜像基于ubuntu:22.04,aarch64 镜像基于openeuler/openeuler:24.03:
docker build -t ascendnpu-ir:latest -f docker/Dockerfile.x86_64 .

运行容器时需挂载 NPU 设备(--device=/dev/davinci0等 davinci 设备、davinci_manager、devmm_svm、hisi_hdc)并挂载 dcmi、npu-smi、驱动目录等;进入后可直接使用bishengir-compile等工具,可用bishengir-compile --version查看版本信息。

运行测试与版本配套

运行测试

在build目录下执行以下命令,通过llvm-lit运行 BiShengIR 测试套:

cmake --build . --target "check-mlir;check-bishengir"

也可以直接指定测试路径执行:

./bin/llvm-lit ../bishengir/test ./bin/llvm-lit ../bishengir/test/bishengir-compile/commandline.mlir

测试通过判定:命令退出码为 0 且Failed为 0 即通过;其中PASS(正常通过)、UNSUPPORTED(当前环境不支持)、Expectedly Failed(预期失败且实际失败)均计入通过;FAIL、XPASS(预期失败但实际通过)、UNRESOLVED、TIMEOUT计入失败。

版本配套说明

为保证编译与运行稳定性,需要严格按照 版本配套说明 配置环境:

AscendNPU IR 版本Gitcode 分支依赖 CANN 版本硬件支持
v2.0.0release/v2.0.xCANN 9.2.0Ascend 950PR&950DT 系列产品、Atlas A3 系列产品、Atlas A2 系列产品
v1.2.0release/v1.2.xCANN 9.1.0Ascend 950PR&950DT 系列产品、Atlas A3 系列产品、Atlas A2 系列产品
v1.1.0release/v1.1.xCANN 9.0.0Atlas A3 系列产品、Atlas A2 系列产品
v1.0.0release/v1.0.0CANN 8.5.0Atlas A3 系列产品、Atlas A2 系列产品

如需保留当前 CANN 版本又使用新特性,可参考 版本配套说明 中“从新版 CANN 工具包提取 AscendNPU IR 组件替换旧版本”的操作步骤(通过--noexec解包、提取ascendnpu-ir_*.run子包并替换bishengir/bisheng_compiler目录)。

Python 配套:AscendNPU IR 同时提供 Python wheel 包,可通过pip install ascendnpu-ir安装,支持v1.0.0对应 Python>=3.9,<=3.12、v1.1.0对应 Python>=3.10,<=3.13。安装后可调用ascendnpuir.compile接口直接编译 MLIR 字符串生成目标文件(示例见 版本配套说明)。

端到端示例:VecAdd 从 MLIR 到上板执行

README_zh.md将端到端示例指向 bishengir/test/Integration/README_zh.md,仓库中 VecAdd 示例 是一个完整的最小可运行示例,展示了“MLIR → 设备端二进制 → host 端封装 → 上板执行”的完整链路。

第一步:编写 HIVM 层 MLIR

以下 add.mlir 实现了两个 16 元素 int16 向量的加法:先从全局内存gm加载到片上统一缓冲区ub,执行hivm.hir.vadd,再写回全局内存:

module { func.func @add(%arg0: memref<16xi16, #hivm.address_space<gm>>, %arg1: memref<16xi16, #hivm.address_space<gm>>, %arg2: memref<16xi16, #hivm.address_space<gm>>) attributes {hacc.entry, hacc.function_kind = #hacc.function_kind<DEVICE>} { %alloc = memref.alloc() : memref<16xi16, #hivm.address_space<ub>> hivm.hir.load ins(%arg0 : memref<16xi16, #hivm.address_space<gm>>) outs(%alloc : memref<16xi16, #hivm.address_space<ub>>) %alloc_0 = memref.alloc() : memref<16xi16, #hivm.address_space<ub>> hivm.hir.load ins(%arg1 : memref<16xi16, #hivm.address_space<gm>>) outs(%alloc_0 : memref<16xi16, #hivm.address_space<ub>>) %alloc_1 = memref.alloc() : memref<16xi16, #hivm.address_space<ub>> hivm.hir.vadd ins(%alloc, %alloc_0 : memref<16xi16, #hivm.address_space<ub>>, memref<16xi16, #hivm.address_space<ub>>) outs(%alloc_1 : memref<16xi16, #hivm.address_space<ub>>) hivm.hir.store ins(%alloc_1 : memref<16xi16, #hivm.address_space<ub>>) outs(%arg2 : memref<16xi16, #hivm.address_space<gm>>) return } }

这里可以看到 HIVM 方言的典型表达:#hivm.address_space<gm>/#hivm.address_space<ub>区分全局内存与片上缓冲,hacc.entry与hacc.function_kind<DEVICE>标记设备端入口函数。

第二步:编译设备端二进制

export ASCEND_HOME_PATH=/usr/local/ascend-toolkit/latest # 按实际安装路径设置 bishengir-compile add.mlir -enable-hivm-compile -o kernel.o

生成的kernel.o即为可在 NPU 上执行的算子二进制。注意:若bishengir-compile为源码自编译版本,需在构建时添加-t(--build-bishengir-template)参数构建模板库,端到端编译依赖该组件;--target=${soc_version}用于指定目标硬件型号,默认为Ascend910B1。

第三步:编写 host 端封装程序并执行

VecAdd/main.cpp 演示了 CANN runtime 的标准调用流程:aclInit初始化 →aclrtSetDevice设置设备 →aclrtCreateStream创建流 → 通过rtDevBinaryRegister+rtFunctionRegister注册kernel.o中的算子 →aclrtMalloc/aclrtMemcpy准备输入输出数据 →rtKernelLaunch启动核函数 →aclrtSynchronizeStream同步流 → 回拷并对比结果。

该 host 程序对应的 CMake 构建配置见 VecAdd/CMakeLists.txt,它链接runtime与ascendcl库,构建出的可执行文件为bishengir-npu-hivm-vec-add。构建集成测试需要在 CMake 选项中追加-DBISHENGIR_BUILD_EXAMPLES=ON(同时必须使能-DBSPUB_DAVINCI_BISHENGIR=ON),构建完成后./bin目录下即出现该可执行文件。示例运行后输出片段如下(部分文本省略):

i0 Expect: 1 Result: 1 i1 Expect: 2 Result: 2 i2 Expect: 3 Result: 3 i3 Expect: 4 Result: 4

该示例同时被 main.cpp 头部的 lit 测试注释(RUN:/CHECK:)纳入端到端测试套,bishengir-compile编译加FileCheck校验结果的模式可供后续编写自定义算子测试时参考。

文档工程:Sphinx 双语文档的构建方式

README_zh.md对docs/目录下的 Sphinx 文档工程做了约定:通过成对的 Markdown 源文件提供英文与中文双语文档,docs/(含docs/source/)下的目录名与文件名统一采用snake_case小写下划线风格(如quick_start/、installing_guide.md)。英文入口页为docs/source/en/index.rst,中文入口页为docs/source/zh_cn/index.rst。

在仓库根目录下构建文档:

make -C docs html # 仅英文 → docs/_build/en make -C docs html-zh # 仅中文 → docs/_build/zh_cn make -C docs html-all # 中英文均构建

全新基础环境需先按 docs/README_zh.md 安装系统包与 Python 依赖(Ubuntu 22.04 下需通过 pip 安装 cmake、ninja,因为系统源中的 CMake 3.22 / Ninja 1.10 低于文档构建工具要求的 CMake ≥ 3.28、Ninja ≥ 1.12)。构建后可本地预览(python3 -m http.server启动 HTTP 服务)或在 Read the Docs 上部署(通过READTHEDOCS_LANGUAGE环境变量区分en/zh_CN并关联翻译项目实现语言切换)。

许可与社区

本项目采用 Apache License v2.0,仓库还包含 CONTRIBUTING 指南 等社区协作文档。如需进一步了解 AscendNPU IR 的完整能力与最新特性,建议以 中文文档入口 为主线,依次阅读 简介、架构设计、构建安装 与 编译执行示例,并结合仓库内 bishengir/test 下的数百个 MLIR 测试用例深入理解各方言语义。

  • 编译器
  • 人工智能
  • Ascend
  • CANN

【免费下载链接】AscendNPU-IR

AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优

项目地址:https://gitcode.com/Ascend/AscendNPU-IR
点击查看免费下载
上一篇:在 AWS 上自托管 BentoPDF:S3 + CloudFront 静态部署完整指南
下一篇:TanStack Table ColumnOffsetsByPosition 接口详解:列偏移映射与固定列区域定位机制

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/14 3:14:24

Unity Windows原生窗口控制:无边框与状态栏适配实战

1. 项目概述&#xff1a;为什么在Unity里“动”Windows原生窗口是个刚需做Unity桌面应用的开发者&#xff0c;尤其是开发工具类、工业控制面板、数字孪生看板或者需要深度集成Windows系统行为的项目时&#xff0c;迟早会撞上这个墙&#xff1a;Unity默认的窗口管理太“温柔”了…

作者头像 李华
网站建设 2026/10/14 3:13:42

Python爬虫必备:同步与异步HTTP库全解析

在进行数据分析以及竞品调研的时候, 首先需要明确, 最基础也是最关键的一个步骤, 就是必须把数据从网络上面抓取下来。而在整个过程中里最常用的两个 HTTP 库是同步的和异步的这两个&#xff08;具体的库名称可能需要读者自行对应上下文填补空缺&#xff09;, 这两者加在一起就…

作者头像 李华
网站建设 2026/10/14 3:13:22

Coze智能体搭建实战:从零跑通工作流与Web应用

1. 这不是“又一个Coze教程”&#xff0c;而是一份能让你真正跑通第一个智能体的实操手记我带过不少刚接触Coze的朋友&#xff0c;从某高校实验室的研究生&#xff0c;到某公司转型做AI产品的运营同事&#xff0c;再到完全没写过代码的自由职业者。他们问得最多的问题从来不是“…

作者头像 李华
网站建设 2026/10/14 3:12:22

CSDN + AI:程序员的新生产力 (e 付费专栏)

1. 引言:AI 时代,程序员的生产力正在被重新定义 从代码补全到智能问答,从文档生成到代码审查,AI 正在以前所未有的速度渗透进程序员的日常工作流。作为国内最大的开发者社区,CSDN 也在积极拥抱这一趋势,将 AI 能力融入内容创作、技术学习和代码开发的全链路。本文将从多…

作者头像 李华
网站建设 2026/10/14 3:11:12

douyin-downloader 完整指南:一条命令下载抖音无水印视频

douyin-downloader 完整指南&#xff1a;一条命令下载抖音无水印视频 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallback su…

作者头像 李华