我正在研究加速大部分C++代码的方法,这些代码具有用于计算jacobians的自动衍生产品.这涉及在实际残差中做一些工作,但大部分工作(基于异形执行时间)是在计算雅可比人.
这使我感到惊讶,因为大多数雅各比人都是从0和1向前传播,因此工作量应该是功能的2-4倍,而不是10-12倍.为了模拟大量的jacobian工作是什么样的,我用一个点积(而不是sin,cos,sqrt和更多将在真实情况下)制作了一个超级极小的例子,编译器应该能够优化到单个返回值:
#include <Eigen/Core>
#include <Eigen/Geometry>
using Array12d = Eigen::Matrix<double,12,1>;
double testReturnFirstDot(const Array12d& b)
{
Array12d a;
a.array() = 0.;
a(0) = 1.;
return a.dot(b);
}
Run Code Online (Sandbox Code Playgroud)
哪个应该是一样的
double testReturnFirst(const Array12d& b)
{
return b(0);
}
Run Code Online (Sandbox Code Playgroud)
我很失望地发现,如果没有启用快速数学运算,GCC 8.2,Clang 6或MSVC 19都无法对具有0的矩阵的天真点积进行任何优化.即使使用快速数学(https://godbolt.org/z/GvPXFy),GCC和Clang中的优化也很差(仍然涉及乘法和加法),并且MSVC根本不做任何优化.
我没有编译器的背景,但是有这个原因吗?我相当肯定,即使恒定折叠本身不会导致加速,在很大比例的科学计算中能够做更好的恒定传播/折叠会使更多的优化变得明显.
虽然我有兴趣解释为什么在编译器方面没有这样做,但我也对在实际方面可以做什么感兴趣,以便在面对这些模式时更快地使我自己的代码.
c++ compiler-construction automatic-differentiation eigen ceres-solver
的本征库可以映射现有存储器到本征矩阵.
float array[3];
Map<Vector3f>(array, 3).fill(10);
int data[4] = 1, 2, 3, 4;
Matrix2i mat2x2(data);
MatrixXi mat2x2 = Map<Matrix2i>(data);
MatrixXi mat2x2 = Map<MatrixXi>(data, 2, 2);
Run Code Online (Sandbox Code Playgroud)
我的问题是,如何从特征矩阵(例如Matrix3f m)得到c数组(例如float [] a)?什么是特征矩阵的真实布局?真实数据是否存储在普通c数组中?
我之前已经看过它,但我不记得如何有效地初始化具有相同长度Eigen::Vector的已知std::vector长度.这是一个很好的例子:
std::vector<double> v1 = {1.0, 2.0, 3.0};
Eigen::Vector3d v2; // Do I put it like this in here: v2(v1) ?
v2 << v1[0], v1[1], v1[2]; // I know you can do it like this but
// I am sure i have seen a one liner.
Run Code Online (Sandbox Code Playgroud)
我已经仔细阅读了有关高级矩阵初始化的这一页,但没有明确解释执行此操作的方法.
我正在查看性能基准:http://eigen.tuxfamily.org/index.php?title = Benchmark
我不禁注意到,eigen似乎始终优于所有专业供应商库.问题是:怎么可能?可以假设mkl/goto将使用处理器特定的调谐代码,而特征是相当通用的.
请注意这个http://download.tuxfamily.org/eigen/btl-results-110323/aat.pdf,基本上是一个dgemm.对于N = 1000,Eigen大约为17Gf,MKL仅为12Gf
我有两个特征矩阵,我想连接它们,就像在matlab中一样 cat(0, A, B)
在本征中有什么相同的东西吗?
谢谢.
从我读到的关于Eigen(这里)的内容来看,它似乎operator=()充当了懒惰评估的"障碍" - 例如它导致Eigen停止返回表达式模板并实际执行(优化的)计算,将结果存储到左边的=.
这似乎意味着一个人的"编码风格"对性能产生影响 - 即使用命名变量来存储中间计算的结果可能会对计算的某些部分进行"太早"评估,从而对性能产生负面影响. .
为了验证我的直觉,我写了一个例子并对结果感到惊讶(完整的代码在这里):
using ArrayXf = Eigen::Array <float, Eigen::Dynamic, Eigen::Dynamic>;
using ArrayXcf = Eigen::Array <std::complex<float>, Eigen::Dynamic, Eigen::Dynamic>;
float test1( const MatrixXcf & mat )
{
ArrayXcf arr = mat.array();
ArrayXcf conj = arr.conjugate();
ArrayXcf magc = arr * conj;
ArrayXf mag = magc.real();
return mag.sum();
}
float test2( const MatrixXcf & mat )
{
return ( mat.array() * mat.array().conjugate() ).real().sum();
}
float test3( const MatrixXcf & mat …Run Code Online (Sandbox Code Playgroud) 我一直试图找到一种方法来计算Eigen中矢量的大小,但我无法做到.如果它不存在,有人可以提供函数名称吗?
我可以创建一个完成工作的全局方法,但我不愿意.
是否有可逆的方式将OpenCV cv::Mat对象转换为Eigen::Matrix?
例如,某种做法:
cv::Mat cvMat;
Eigen::Matrix eigMat;
camera->retrieve(cvMat);
// magic to convert cvMat to eigMat
// work on eigMat
// convert eigMat back to cvMat
imshow("Image", cvMat);Run Code Online (Sandbox Code Playgroud)
我已经尝试使用cv2eigen和eigen2cv,但由此产生的cvMat完全是错位的,我不知道是什么原因.尺寸是正确的,但图形完全被破坏,所以可能是每像素字节或数据大小问题?
他们有许多链接反过来但我无法在我的特定情况下找到从Eigen :: Matrix或Eigen :: VectorXd获取std :: vector.
有两个int矩阵A和B,超过1000行和10K列,我经常需要将它们转换为float矩阵以获得加速(4x或更多).
我想知道为什么会这样?我意识到有许多优化和矢量化,如AVX等,继续浮点矩阵乘法.但是,对于整数(如果我没有记错的话),有指令如AVX2.并且,不能使用SSE和AVX作为整数?
为什么在矩阵代数库(如Numpy或Eigen)下面没有启发式来捕获它并像浮点一样更快地执行整数矩阵乘法?
关于已接受的答案:虽然@ sascha的答案非常有用且相关,@ chatz的答案是int乘以int的实际原因,无论是否存在BLAS整数矩阵运算.
eigen ×10
c++ ×9
matrix ×2
performance ×2
arrays ×1
ceres-solver ×1
numpy ×1
opencv ×1
readability ×1
vector ×1