Eigen3 使用与实例

作为C++下常用的矩阵库,Eigen3“开袋即食”的特点让使用者省去了很多安装和环境配置的麻烦,下面我将根据官方文档和自己使用经验,为大家介绍Eigen3的使用方法。

一、下载与安装

Eigen3作为C++下矩阵库,使用时只需引用库中的头文件即可,库文件有两种方法安装使用:

  1. Ubuntu下 sudo apt-get install libeigen3-dev,库文件默认安装在/usr/include/eigen3/Eigen,使用时注意路径。
  2. 如果需要在集群中使用并且没有root权限,可以手动从官网下载库文件,将库放在工程lib文件夹中,在引用时用相对路径引用,编译时也无需指定库路径。

以在ubuntu下第二种方式为例,给出使用示例:
创建示例文件夹并进入:

mkdir eigen3_example
cd eigen3_example

下载库文件:
wget https://gitlab.com/libeigen/eigen/-/archive/3.3.7/eigen-3.3.7.tar.bz2
解压:tar -xjvf eigen-3.3.7.tar.bz2;
创建lib文件夹并将eigen3核心部分复制进文件夹:

mkdir lib
cp -R eigen-3.3.7/Eigen/ lib/Eigen

根据Eigen3官方文档,我们常用的与矩阵和向量相关的内容包含如下:在这里插入图片描述
一般情况下#include <Eigen/Dense>已经可以满足我们对于Eigen3库的使用。
下面我们在eigen3_example目录下创建第一个测试代码文件:
vim eigen_test1.cpp
复制以下代码,测试eigen3库是否可以正常使用:

#include <iostream>
#include "./lib/Eigen/Dense"
using namespace std;
using namespace Eigen;
int main()
{
    MatrixXd test = MatrixXd::Zero(10,10);
    cout<<test<<endl;
}

复制完成按ESC输入:wq回车即可保存。
编译:g++ -o eigen3_test1 eigen3_test1.cpp
运行:./eigen3_test1

在这里插入图片描述
至此,通过方法二我们实现了Eigen3库的下载和引用使用,需要注意的是可以看到在头文件的引用中:#include "./lib/Eigen/Dense"需要根据真实工程项目文件具体目录结构进行调整。

二、向量与矩阵的申明和初始化

在Eigen3库中包含两种基本数据结构,向量Vector和矩阵Matrix,向量是矩阵的一维特殊形式,所以大部分矩阵的操作在向量上也适用,以矩阵的申明和初始化为例进行说明。

矩阵申明

  1. 静态矩阵(fixed-size matrices)
    根据官方文档,当需要使用的矩阵size已知且小于16时(例如小于4x4矩阵),推荐使用静态矩阵实现。通过以下代码,我们分别申明了4x4的double型矩阵,3x3的float型矩阵,2x2的int型矩阵:
Matrix4d mat4d;
Matrix3f mat3f;
Matrix2i mat2i;
  1. 动态矩阵(dynamic-size matrices)
    当矩阵size大于16时,推荐使用动态矩阵。以下方式什么的三个动态矩阵实际大小均为0x0,只有在进一步明确其维度时,程序才会为其动态的分配内存空间。
MatrixXd matd;
MatirxXf matf;
MatrixXi mati;

矩阵初始化

Eigen3库中的矩阵和向量下标均是从0开始,通过重载符号,实现了使用 mat(index_row, index_col) 对矩阵具体位置进行取值和赋值操作,如下我们申明一个动态矩阵,并在申明时确定其为2x2大小,通过指定下标的形式为其幅值:

MatrixXd mat(2, 2);
mat(0, 0) = 0;
mat(0, 1) = 1;
mat(1, 0) = 2;
mat(1, 1) = 3;

这种方法和利用重载的<<运算符赋值一致:

mat << 0, 1,
	   2, 3;

一般情况下,为避免使用了申明却未全部初始化的动态矩阵,申明矩阵时可主动将其初始化为零矩阵:

MatrixXd mat = MatrixXd::Zero(rows, cols);

静态矩阵赋值方式和动态矩阵完全一致,但是要注意申明的矩阵维度,如果出现越界赋值,例如如下代码:

Matrix2d test;
test<< 1, 2, 3,
       4, 5, 6,
       7, 8, 9;
cout<<test<<endl;

运行时程序会提示“Too many rows passed to comma initializer (operator<<)”

三、矩阵的基本运算

重载的数乘与矩阵乘法

Eigen3库重载了矩阵的数乘和矩阵乘法,下面以2
x2矩阵为例,探究数乘与矩阵乘法:

MatrixXd mat(2, 2);
mat << 1, 2,
	   3, 4;
cout << (mat * 2) << endl;
cout << (mat / 2) << endl;

结果如下:
2 4
6 8
0.5   1
1.5   2

对于基本的矩阵运算,案例如下:

MatrixXd mat(2, 2);
mat << 1, 2,
       3, 4;
MatrixXd a = mat/2;
MatrixXd b = mat * a;
cout<<mat<<endl;
cout<<a<<endl;
cout<<b<<endl;

结果如下:
1 2
3 4

0.5   1
1.5   2

3.5   5
7.5  11

可以看到矩阵b已经是按照矩阵相乘法则进行计算,对于矩阵加法和减法,需要注意必须是相同纬度的矩阵才可以进行操作。

矩阵块操作

Eigen3提供了丰富的块操作接口,并且打开编译器优化后,块操作部分会自行实现优化,其中最为重要的三种操作为矩阵取行、列和块:

MatrixXd mat(3, 3);
mat << 1, 2, 3,
	   4, 5, 6,
	   7, 8, 9;
VectorXd row  = mat.row(0);
VectorXd col  = mat.col(0);
MatrixXd matblock = mat.block(0, 0, 2, 1);
cout << row <<endl;
cout << col <<endl;
cout << matblock <<endl;
结果为:
row: 1 2 3
col: 1 4 7
matblock: 1 4

其中row获取了mat矩阵的第一行数据,col获取了mat矩阵的第一列数据,此处同样展示了矩阵与向量之间的互相转换。block函数包含四个输入,mat.block(a, b, c, d),其中a和b分别表示具体的起始行列下标,c和d表示以(a, b)所在行列开始,取的行数和列数。以matlab矩阵操作为例,可将其等同为:
mat.block(x, y, rows, cols) = mat(x:x+rows-1, y:y+cols-1)

其他常用矩阵运算

转置:mat.transpose()
内积:mat_a.dot(mat_b)
平均值:mat.mean()
和:mat.sum()
最大值:mat.maxCoeff()
最小值:mat.minCoeff()
迹:mat.trace()
矩阵大小:mat.size()
矩阵行数:mat.rows()
矩阵列数:mat.cols()
矩阵置零:mat.setZero()
矩阵置一:mat.setOnes()

四、优化

开启mkl优化

在使用Intel处理器并且已经安装好mkl库的情况下,可通过宏开启Eigen3的mkl优化,需要在引用头文件前加入:

#define EIGEN_USE_MKL_ALL
#include "./lib/Eigen/Dense"

并且在编译时调用mkl库。

开启编译优化

使用g++或icpc进行编译时,可通过优化指令开启优化,一般使用 -o2 -march=core-avx2 -lpthread -fopenmp 进行优化,优化后的运行速度提升显著。

关闭Eigen3的Debug模式

#define EIGEN_NO_DEBUG
#define EIGEN_USE_MKL_ALL
#include "./lib/Eigen/Dense"

在确保程序无误的情况下,关闭Debug断言,可以提升程序效率。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值