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

使用Eigen::Ref<>传递矩阵行作为左值引用的问题

解决Eigen中传递.row(i)作为左值引用的性能问题

问题背景

现有代码可正常运行,但性能分析显示Eigen::internal::dense_assignment_loop::run占用44.8%的耗时,推测是循环中临时变量tmp的拷贝操作导致:

for ( index_type i = 0; i <= n; ++i )
{
  de_casteljau( tmp, B_v[ i ], v );
  temp_cp.row( i ) = tmp;
}

尝试直接传递temp_cp.row(i)以消除拷贝,修改后的代码如下:

for ( index_type i = 0; i <= n; ++i )
{
  de_casteljau( temp_cp.row( i ), B_v[ i ], v );
}

编译错误情况

clang报错提示无法匹配函数调用,原因是de_casteljau的第一个参数要求左值,但.row(i)返回的是临时Block对象(右值):

error: no matching function for call to 'de_casteljau'
note: candidate function [with Derived1 = Eigen::Block<Eigen::Matrix<double, -1, 3>, 1, 3>, Derived2 = Eigen::Map<Eigen::Matrix<double, -1, 3>, 0, Eigen::Stride<1, -1>>] not viable: expects an lvalue for 1st argument
   27 |       void de_casteljau(Eigen::MatrixBase<Derived1> &p, const Eigen::MatrixBase<Derived2> &cp, const typename Derived2::Scalar &t)

尝试将de_casteljau的函数声明改为使用Eigen::Ref,但写法错误导致新的编译错误:

template < typename Derived1, typename Derived2 >
void de_casteljau( Eigen::Ref < Eigen::MatrixBase < Derived1 > > p, const Eigen::MatrixBase < Derived2 > & cp, const typename Derived2::Scalar & t )

错误信息:

error: no matching function for call to 'de_casteljau'
note: candidate template ignored: could not match 'Ref' against 'Matrix'
   27 |       void de_casteljau(Eigen::Ref < Eigen::MatrixBase<Derived1> > p, const Eigen::MatrixBase<Derived2> &cp, const typename Derived2::Scalar &t)

要求在不修改de_casteljau现有调用点的前提下解决问题。

正确解决方案

将de_casteljau的第一个参数改为Eigen::Ref<Derived1>(而非Eigen::Ref<Eigen::MatrixBase<Derived1>>),让模板参数直接推导目标类型,同时兼容左值和右值表达式:

修改后的函数声明

template < typename Derived1, typename Derived2 >
void de_casteljau( Eigen::Ref<Derived1> p, const Eigen::MatrixBase<Derived2> & cp, const typename Derived2::Scalar & t )

函数实现保持不变

{
  // do some checks on incoming matrix dimensions
  assert( p.cols() == cp.cols() );

  Eigen::Matrix < typename Derived2::Scalar, Eigen::Dynamic, Eigen::Dynamic > Q( cp );
  typename Derived2::Scalar oneminust( 1 - t );
  typename Derived2::Index k, i;

  for ( k = 1; k < Q.rows(); ++k )
  {
    for ( i = 0; i < Q.rows() - k; ++i )
    {
      Q.row( i ) = oneminust * Q.row( i ) + t * Q.row( i + 1 );
    }
  }

  p = Q.row( 0 );
}

原理说明

  • Eigen::Ref<Derived1>可以绑定任意可赋值的Eigen表达式,包括左值(如point_type对象)和临时右值(如.row(i)返回的Block对象),无需修改原有调用点。
  • 这种写法既消除了临时变量tmp的拷贝操作,又保持了代码的兼容性,完全匹配性能优化的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 00:55:57