eigen3 相关问题

Eigen是线性代数的C ++模板库:矩阵,向量,数值求解器和相关算法。



eigen矩阵乘法效率远低于环路遍历

#包括 #include #include #include int main() { const int num_points = 300000000; eigen ::matrix #include <Eigen/Dense> #include <iostream> #include <random> #include <chrono> int main() { const int num_points = 300000000; Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic> init_points(num_points, 3); Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic> transformed_points(num_points, 3); std::mt19937 rng(42); std::uniform_real_distribution<float> dist(-100.0f, 100.0f); for (int i = 0; i < num_points; ++i) { init_points(i, 0) = dist(rng); // x init_points(i, 1) = dist(rng); // y init_points(i, 2) = dist(rng); // z } float theta = 3.14159265358 / 4; // pi/4 Eigen::Matrix3f rotation; rotation = Eigen::AngleAxisf(theta, Eigen::Vector3f::UnitZ()); Eigen::Vector3f translation(10.0f, 20.0f, 30.0f); auto start_time = std::chrono::high_resolution_clock::now(); //transformed_points = init_points * rotation; //uncomment this line to use the Matrix multiply version //transformed_points.rowwise() += translation.transpose(); //uncomment this line to use the Matrix multiply version for (int i = 0; i < num_points; ++i) //comment this for loop to use the Matrix multiply version { Eigen::Vector3f v = init_points.row(i).transpose(); v = rotation * v; v += translation; transformed_points.row(i) = v.transpose(); } auto end_time = std::chrono::high_resolution_clock::now(); std::chrono::duration<double, std::milli> duration_ms = end_time - start_time; std::cout << "total consume: " << duration_ms.count() << "ms" << std::endl; std::cout << "first 5 points:(x,y,z)" << std::endl; for (int i = 0; i < 5; ++i) { std::cout << "("<< transformed_points(i, 0) << ","<< transformed_points(i, 1) << ", " << transformed_points(i, 2) << ")" << std::endl; } return 0; } I当前在通过点云采样获得的对象上执行坐标转换。我需要先旋转一组点,然后翻译它们以获得转换的点云。 这个点云数据总共包含300,000,000点,我正在使用eigen的动态阵列进行存储。 上面的代码是一个测试示例,我在其中初始数字初始化了300,000,000点,然后执行旋转和翻译操作。该代码既包括循环遍历版本和矩阵乘法版本。要使用矩阵乘法,您只需要删除我发表评论的两行并评论前循环部分。 the是对循环遍历和矩阵乘法版本所消耗的时间的比较: 1。对于旋转和翻译操作,我尝试将所有300,000,000点乘以旋转矩阵,然后添加翻译向量。此操作在我的i7-13700k cpu上大约需要2044ms。 2。我写了一个循环遍历每个点并逐一旋转和翻译。总时间仅为600ms。 我知道eigen使用许多CPU指令集来优化矩阵乘法,并且我正在使用启用了各种SIMD和AVX优化的英特尔ICC编译器。为什么在这里的前横梁比矩阵乘法快3倍? 加上,是否有任何空间可以进一步优化上述代码? 有人可以帮助分析吗?我非常感谢它。 PS:我确实有优化的打开,因为在优化的情况下关闭了所花费的时间比现在要高得多。我的意思是,当我打开优化时,for循环比单独进行矩阵乘法更快 我刚刚进行了一些时间测量。由于我没有与您相同的CPU,并且您没有指定所使用的确切编译器选项,因此效果可能会或可能不会有所不同。 我测试了: Intel(R)Oneapi DPC ++/C ++编译器2025.0.4 编译器标志:-dndebug -o3 -march =i7-9850H上的本机 以下所有值是3个测量值的中间: 逐行的弯曲率花费了1247.91ms。 矩阵乘版本最初采用2583.93ms。 使用Noalias(如transformed_points.noalias() = init_points * rotation;中)时,矩阵乘版本为1451.23ms。 noalias有助于摆脱临时性,请参阅https://eigen.tuxfamily.org/dox/group__topicaliasing.html 当将行和列切换时,将固定尺寸从Eigen::Dynamic切换到3时,iThe矩阵乘法版本花费了1278.85ms。由于eigen默认为列是列 - 这意味着每个点的x,y和z现在彼此隔绝。 其他优化可能是可能的,但至少现在是初始的逐行环和矩阵乘法所需(几乎)运行时间的时间。 这是最终代码: const int num_points = 300000000; Eigen::Matrix<float, 3, Eigen::Dynamic> init_points(3, num_points); Eigen::Matrix<float, 3, Eigen::Dynamic> transformed_points(3, num_points); std::mt19937 rng(42); std::uniform_real_distribution<float> dist(-100.0f, 100.0f); for (int i = 0; i < num_points; ++i) { init_points(0, i) = dist(rng); // x init_points(1, i) = dist(rng); // y init_points(2, i) = dist(rng); // z } float theta = -3.14159265358 / 4; // minus to transpose/invert rotation Eigen::Matrix3f rotation; rotation = Eigen::AngleAxisf(theta, Eigen::Vector3f::UnitZ()); Eigen::Vector3f translation(10.0f, 20.0f, 30.0f); auto start_time = std::chrono::high_resolution_clock::now(); transformed_points.noalias() = rotation * init_points; transformed_points.colwise() += translation; auto end_time = std::chrono::high_resolution_clock::now(); std::chrono::duration<double, std::milli> duration_ms = end_time - start_time; std::cout << "total consume: " << duration_ms.count() << "ms" << std::endl; std::cout << "first 5 points:(x,y,z)" << std::endl; for (int i = 0; i < 5; ++i) { std::cout << "("<< transformed_points(0, i) << ","<< transformed_points(1, i) << ", " << transformed_points(2, i) << ")" << std::endl; }

回答 1 投票 0

如何正确初始化 Eigen::Matrix<std::optional<int>>

我正在使用 Eigen::Matrix> 但我不知道如何初始化它。 对于数字类型, Matrix::Zero() 效果很好,但是当我使用 std::Optional 时,我想

回答 1 投票 0

在 Eigen 中,对于预分配的矩阵,赋值运算符是否会尝试重用现有内存?

考虑以下特征代码片段: 选项1 特征::MatrixXf A (m, n), B; B=A; 选项2 特征::MatrixXf A (m, n), B (m, n); B=A; 在选项 1 中,我假设 B 开始时的大小为 (0, 0)...

回答 1 投票 0

如何高效组装 FEM 稀疏矩阵

全部成交, 感谢您花时间阅读我的问题。 我正在使用 Eigen3.3.4(http://eigen.tuxfamily.org/index.php?title=Main_Page) 编写一些 FEM 代码。 我读了Eigen3.3.4文档,在这个

回答 2 投票 0

为什么在 Eigen 中使用负索引数组进行索引不会引发断言错误?

我正在从Python移植一种算法,它使用一个数组来索引另一个数组。在Python算法中,索引数组中使用-1值作为标志来指示无效数据。我预计这会雷...

回答 1 投票 0

Eigen::Vector3f 逐元素比较并将个体设置为零

我有3个向量,用于存储笛卡尔坐标系中沿x、y和z轴的坐标、速度和加速度。 我正在检查这些值中的任何一个是否接近 0(零)并且如果...

回答 1 投票 0

从 lambda 中返回表达式时 Eigen 结果错误

我正在尝试在 lambda 中使用此函数的主体: Vector3d fun(Vector3d const& 点) { Vector3d const b{ 0., 0., 30. }; 返回 b + point.normalized(); } 但当结果是...

回答 1 投票 0

Eigen3针对AVX2指令集错误进行优化

我正在尝试将 Eigen3 前端与 Intel MKL 后端结合使用。 我正在针对 AVX2 指令集优化程序。 当我定义 AVX2 时,我得到了下面提到的内容。 如果我不定义 AVX2,我会得到 SSE 并且...

回答 1 投票 0

当 Block 的模板 arg Row 等于 1 时,将 Eigen Block 分配给 Eigen Ref 编译错误

我写了一段代码: 特征::矩阵 m(5, 5); 自动 r = m.topRows<1>(); 本征::Ref> r2(r) 这将导致编译

回答 1 投票 0

C++20 格式的 Eigen3 库

我正在尝试使用 c++20 格式而不是 Eigen::IOFormat 打印 Eigen::Array 或 Eigen::Matrix。 我想用说明符控制矩阵中元素的精度和对齐方式,对于

回答 2 投票 0

特征矩阵和向量之间的逐元素运算

以下代码进行矩阵和向量之间的减法。该向量在运行时自动广播为形状 (30, 7)。但如果 num 和 sub_value 被声明为动态形状的 Matrix/

回答 2 投票 0

为什么Eigen库中double的计算速度比float快3倍?

这是我的代码。我使用 double 类型创建了一组矩阵和向量乘法,并使用 float 类型创建了另一组。两组乘法在 for 循环中执行了 300 万次,a...

回答 1 投票 0

将具有双精度数组的自定义结构映射到 Eigen::Matrix

我有来自第三方库的c结构: typedef 结构 Point3d { #ifdef __cplusplus 枚举{大小= 3}; typedef 双值类型; ///< type

回答 1 投票 0

HighFive - 将数据集读入 Eigen3 矩阵

我正在尝试仅头文件库 HighFive,它为 libhdf5 提供了更方便的接口。提供的示例展示了如何从 Eigen::MatrixXd 填充数据集....

回答 1 投票 0

使用线性索引列表在特征值中的输入和输出矩阵之间进行映射

假设我有 3 个 2D 矩阵: 移位数据 - 大小的复数双精度 [tSize*TXSize,xSize] 数据 - 大小的复数双精度 [tSize*TXSize,xSize] 索引 - 大小的整数 [tSize,xSize] 我想绘制每一个...

回答 1 投票 0

Eigen:减去两个长度不等的向量,隐式用零填充较短的向量

我正在使用 Eigen 3.4。我想减去两个长度不等的向量,在底部用零填充较短的向量,同时避免重新分配内存。粗略的例子: VectorXd A (4), B...

回答 1 投票 0

尝试从以 .sum() 结尾的链式 Eigen::Tensor 操作中提取标量时出错

我有以下脚本 #包括 #包括 int main() { 使用命名空间特征; // 用任意数据填充张量 张量&...

回答 1 投票 0

g++“忽略不存在的目录”,但实际上存在(仅适用于 CLion + Ninja)

我有一些 C++ 源代码,其中包括以下行: #包括 编译在这一行失败,并出现错误:(为简洁起见,我的源文件名/路径已被编辑。) 文件中包含...

回答 1 投票 0

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.