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

如何基于Eigen快速同时计算平方范数与归一化向量?

优化Eigen中百万次调用的directedInverseSquare函数

问题分析

你的代码中,diff.normalized()和diff.squaredNorm()会重复计算差分向量的平方和:

  • normalized()内部会先调用squaredNorm()得到模长平方,再开根号得到模长,最后完成归一化
  • 后续又单独调用一次squaredNorm()获取模长平方

对于百万次调用的场景,这种重复计算会带来显著的性能开销。而你提到的等价形式R/r³(R为差分向量)可以帮我们复用计算结果,避免重复开销。

优化实现

下面是直接复用平方和计算的优化版本,同时保留原逻辑的正确性:

#include <Eigen/Core>

using Eigen::Vector2d;

inline Vector2d directedInverseSquare(const Vector2d &pos1, const Vector2d &pos2) {
    Vector2d diff = pos2 - pos1;
    const double r_squared = diff.squaredNorm();
    
    // 处理零点避免除以0的情况
    if (r_squared == 0.0) {
        return Vector2d::Zero();
    }
    
    const double r = std::sqrt(r_squared);
    // 等价于 rHat / r_squared,只计算一次平方和+一次开根号
    return diff / (r_squared * r);
}

关键优化点

  1. 复用平方和计算:仅调用一次squaredNorm(),后续通过开根号得到模长r,避免原代码中两次计算平方和的开销
  2. 直接计算等价形式:diff / (r_squared * r)完全等价于原逻辑的rHat / r_squared,但省去了单独生成rHat的步骤
  3. const引用参数:将pos1/pos2改为const Vector2d &,既保证安全性,也有助于编译器进行优化
  4. inline修饰:对于高频调用的函数,inline可以避免函数调用的额外开销

额外性能选项(精度换速度)

如果你的场景对精度要求不高,可以使用Eigen的fastNorm()替代std::sqrt(r_squared),它采用快速平方根近似算法,速度更快:

inline Vector2d directedInverseSquare(const Vector2d &pos1, const Vector2d &pos2) {
    Vector2d diff = pos2 - pos1;
    const double r = diff.fastNorm();
    
    if (r == 0.0) {
        return Vector2d::Zero();
    }
    
    const double r_cubed = r * r * r;
    return diff / r_cubed;
}

Eigen原生函数说明

Eigen并没有直接提供同时返回归一化向量和平方距离的原生函数,但通过上述手动复用计算的方式,已经能达到比原生分开调用更优的性能——本质上是避免了重复的平方和计算,这是原生分开调用无法做到的。

内容的提问来源于stack exchange,提问作者Malmel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 20:35:55