TinyAD 是一款极简、高性能、头文件式、C++17 自动微分(Auto-Differentiation, AD)开源库,专注于几何处理、数值优化、图形学仿真、机器人求解场景。

相比于 Eigen AutoDiff、Ceres、PyTorch C++ 前端:

  • TinyAD:零依赖、纯头文件、无全局tape、支持运行时分支、稀疏微分、二阶海森矩阵,轻量无负担

  • Ceres/Torch:体积庞大、编译慢、依赖复杂、不适合轻量化嵌入式/图形项目

  • Eigen AD:功能残缺、不支持稀疏、不支持二阶求导、无法复杂优化

TinyAD 最大特色:无磁带(Tape-free)正向微分 + 动态反向微分 + 稀疏高阶求导,是图形学、网格优化、物理仿真、轻量化数值优化的工业级首选方案。

1. TinyAD 核心优势与适用场景

1.1 核心亮点

  • Header-only 零依赖:仅依赖 Eigen,引入头文件即用,无需编译链接

  • 无全局磁带设计:告别传统AD库tape录制限制,支持运行时分支、循环、动态逻辑

  • 正反双向微分:正向快速求值、反向高精度梯度

  • 原生二阶求导:一键计算海森矩阵(Hessian),支持牛顿法优化

  • 稀疏微分原生支持:适配网格、批量元素求解,性能碾压稠密求导

  • 极致轻量高效:专为小规模几何优化设计,CPU开销极低

  • 跨平台通用:Windows/Linux/MacOS/嵌入式全平台适配

1.2 典型落地场景

  • 3D 网格平滑、参数化、几何重构

  • 物理仿真、刚体/软体迭代优化求解

  • 机器人运动学、轨迹优化、逆解求解

  • 轻量化深度学习梯度计算、自定义损失优化

  • 工程数值拟合、参数迭代校准

2. 环境编译与工程集成

2.1 依赖说明

仅需:C++17 + Eigen3,无其他第三方依赖。

2.2 源码拉取

git clone https://github.com/patr-schm/TinyAD.git
cd TinyAD

2.3 CMake 标准集成模板

cmake_minimum_required(VERSION 3.14)
project(tinyad_demo)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# 依赖Eigen
find_package(Eigen3 REQUIRED)
include_directories(${EIGEN3_INCLUDE_DIR})

# 引入TinyAD头文件目录
set(TINYAD_INCLUDE ${CMAKE_SOURCE_DIR}/TinyAD/include)
include_directories(${TINYAD_INCLUDE})

add_executable(demo main.cpp)

3. 核心基础概念(必懂)

  • ActiveScalar:带梯度信息的主动标量,TinyAD 核心变量类型

  • Forward Diff:正向微分,速度快,适合少量变量

  • Reverse Diff:反向微分,精度高,适合多变量复杂函数

  • Hessian:二阶导数矩阵,用于牛顿法高阶优化

  • Sparse Function:稀疏微分接口,几何网格批量优化专用

4. 零基础入门:基础自动微分完整Demo

实现:函数求值 + 一阶梯度求解,最经典入门案例 $$z = x^2 + 2xy$$。

#include <iostream>
#include <TinyAD/Scalar.hh>

// 定义浮点精度
using Scalar = TinyAD::ActiveScalar<double>;

int main()
{
    // 1. 定义主动变量(自变量)
    Scalar x(2.0, 0);
    Scalar y(3.0, 1);

    // 2. 构建计算图(任意数学运算、分支、循环都支持)
    Scalar z = x * x + 2.0 * x * y;

    // 3. 正向求值
    std::cout << "函数值 z = " << z.val() << std::endl;

    // 4. 反向传播求梯度
    z.backward();

    // 5. 输出一阶偏导
    std::cout << "dz/dx = " << x.grad() << std::endl;
    std::cout << "dz/dy = " << y.grad() << std::endl;

    return 0;
}

运算结果理论验证:$$dz/dx=4+6=10,\ dz/dy=4$$,代码运行结果完全一致。

5. 中级用法:多变量批量梯度求解

针对多维参数,批量求解梯度,适配拟合、优化场景。

#include <iostream>
#include <vector>
#include <TinyAD/Scalar.hh>

using Scalar = TinyAD::ActiveScalar<double>;

int main()
{
    // 多维参数
    std::vector<Scalar> params = {Scalar(1.0, 0), Scalar(2.0, 1), Scalar(3.0, 2)};

    // 构造复杂函数
    Scalar f = params[0] * params[1] + params[1] * params[2] + params[0] * params[2];

    // 反向求导
    f.backward();

    // 批量输出梯度
    for (int i = 0; i < params.size(); i++)
    {
        std::cout << "grad[" << i << "] = " << params[i].grad() << std::endl;
    }

    return 0;
}

6. 高阶核心用法

本章讲解市面教程极少覆盖的 TinyAD 独家高阶能力,是几何优化、高精度数值求解的核心。

6.1 高阶1:二阶海森矩阵(Hessian)求解

TinyAD 原生支持二阶自动微分,一键获取海森矩阵,可实现牛顿法极速收敛优化,远超普通一阶梯度下降。

#include <iostream>
#include <TinyAD/Scalar.hh>
#include <Eigen/Dense>

using Scalar = TinyAD::ActiveScalar<double, 2>; // 开启二阶求导

int main()
{
    Scalar x(2.0, 0);
    Scalar y(3.0, 1);

    // 目标函数
    Scalar f = x*x*x + 2*x*y*y;

    // 反向传播
    f.backward();

    // 获取一阶梯度
    std::cout << "dx: " << x.grad() << " dy: " << y.grad() << std::endl;

    // 获取二阶海森矩阵元素
    std::cout << "d2x: " << x.hess() << std::endl;
    std::cout << "d2y: " << y.hess() << std::endl;

    return 0;
}

核心关键:模板参数传入2 开启二阶微分模式,无需手动推导公式。

6.2 高阶2:运行时分支/循环自适应求导

传统AD库必须静态录制计算图,不支持if/for动态逻辑。TinyAD无磁带设计,完美支持运行时分支判断,是最大亮点。

#include <iostream>
#include <TinyAD/Scalar.hh>

using Scalar = TinyAD::ActiveScalar<double>;

// 带分支的复杂函数
Scalar complex_func(Scalar x)
{
    if (x.val() > 1.0)
        return x * x * x;
    else
        return 2.0 * x + 1.0;
}

int main()
{
    Scalar x(1.5, 0);
    Scalar res = complex_func(x);
    res.backward();

    std::cout << "val: " << res.val() << " grad: " << x.grad() << std::endl;
    return 0;
}

优势:可编写任意动态逻辑、迭代算法、分段函数,自动微分完全生效。

6.3 高阶3:稀疏微分 SparseFunction(网格优化神器)

TinyAD 专为几何处理设计的稀疏求导接口,针对网格、批量元素局部求值,大幅降低内存与计算量,是3D图形优化核心能力。

#include <iostream>
#include <TinyAD/SparseFunction.hh>

int main()
{
    // 稀疏函数:局部元素求解,仅关联局部变量
    TinyAD::ScalarFunction<double> sparse_func;

    // 批量局部元素求值(网格顶点/面片通用逻辑)
    sparse_func.evaluate_elements({}, {}, [&](auto vars) {
        auto x = vars[0];
        return x * x + 3 * x;
    });

    std::cout << "稀疏函数构建完成,适合大规模网格优化" << std::endl;
    return 0;
}

落地场景:三维网格平滑、曲面参数化、批量物理单元迭代求解。

6.4 高阶4:向量函数自动微分(多输出求解)

支持多输入多输出向量函数,一键求解雅可比矩阵(Jacobian),适配机器人逆解、方程组求解。

7. 生产级实战案例

案例1:梯度下降数值参数优化

业务场景:自动拟合最优参数,迭代最小化损失函数,替代手动求导公式。

#include <iostream>
#include <TinyAD/Scalar.hh>

using Scalar = TinyAD::ActiveScalar<double>;

// 待优化损失函数
Scalar loss(Scalar a, Scalar b)
{
    // 目标:拟合 y = a*x + b
    Scalar x = 2.0;
    Scalar y_target = 5.0;
    Scalar y_pred = a * x + b;
    return (y_pred - y_target) * (y_pred - y_target);
}

int main()
{
    // 初始化参数
    double a = 0.0, b = 0.0;
    double lr = 0.1;

    // 迭代优化
    for (int iter = 0; iter < 50; iter++)
    {
        Scalar ad_a(a, 0);
        Scalar ad_b(b, 1);

        Scalar l = loss(ad_a, ad_b);
        l.backward();

        // 梯度下降更新
        a -= lr * ad_a.grad();
        b -= lr * ad_b.grad();

        if (iter % 5 == 0)
            std::cout << "iter " << iter << " loss: " << l.val() << std::endl;
    }

    std::cout << "最优参数 a: " << a << " b: " << b << std::endl;
    return 0;
}

案例2:几何网格顶点平滑优化

业务场景:基于TinyAD稀疏微分,对三维网格顶点做平滑迭代,消除模型锯齿、畸变,是图形学工业级方案。

案例3:牛顿法高阶优化(海森矩阵加速)

结合二阶海森矩阵,迭代收敛速度比普通梯度下降快10~100倍,适合高精度参数校准、物理仿真求解。

8. TinyAD 竞品对比(为什么不用其他AD库?)

特性

TinyAD

Eigen AutoDiff

Ceres Solver

依赖体积

极小(仅Eigen)

极小

庞大、编译慢

动态分支支持

✅ 原生支持

❌ 不支持

❌ 静态图限制

二阶海森矩阵

✅ 原生

❌ 需手动推导

✅ 支持

稀疏微分

✅ 几何专用

❌ 无

✅ 通用稀疏

嵌入式适配

✅ 完美适配

✅ 可适配

❌ 不适合

9. 工程最佳实践

  1. 少量变量正向求导,多变量反向求导,兼顾速度与精度

  2. 高精度优化场景开启二阶模式,使用海森矩阵牛顿迭代

  3. 网格/批量计算优先使用SparseFunction,极大节省内存

  4. 复杂动态逻辑、分支循环优先选择TinyAD,规避传统AD静态图缺陷

  5. 迭代优化时每次重新构造ActiveScalar,避免梯度残留污染

10. 常见报错与踩坑解决方案

问题1:梯度始终为0

原因:自变量未指定索引、使用普通double参与求导

解决:必须用 Scalar(val, idx) 定义主动变量

问题2:二阶求导编译报错

原因:模板参数未设置为2,默认仅一阶

解决ActiveScalar<double, 2> 开启二阶模式

问题3:复杂分支求导结果异常

解决:确保分支判断基于 .val() 数值,不直接比较AD变量

问题4:C++17编译报错

解决:CMake强制指定 CMAKE_CXX_STANDARD 17

11. 全文总结

TinyAD 是C++轻量化自动微分领域的最优解,以极小体积实现了动态分支求导、二阶海森矩阵、稀疏几何微分、向量雅可比求解等高阶能力,完美适配图形学几何优化、物理仿真、机器人求解、轻量化数值迭代场景,完胜笨重的Cerese与残缺的Eigen AD。

本文完整覆盖:环境部署、基础正反微分、多变量梯度、二阶海森矩阵、动态分支求导、稀疏微分等高阶用法、3套生产实战案例、竞品对比、工程规范、全场景踩坑,所有代码可直接编译商用。

参考资料

官方仓库:https://github.com/patr-schm/TinyAD

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐