如何在C++ ArrayFire与C++ Eigen矩阵之间实现互转?
Eigen与ArrayFire矩阵相互转换方法
1. Eigen 转 ArrayFire
ArrayFire的af::array支持直接从主机端连续内存构造,Eigen矩阵默认是列优先存储(与ArrayFire默认一致),可直接传递数据指针实现转换:
列优先Eigen矩阵转换
#include <Eigen/Dense> #include <arrayfire.h> // 初始化Eigen列优先矩阵 Eigen::MatrixXf eigen_col_mat(3, 3); eigen_col_mat << 1, 2, 3, 4, 5, 6, 7, 8, 9; // 直接转换为ArrayFire数组 af::array af_mat(eigen_col_mat.rows(), eigen_col_mat.cols(), eigen_col_mat.data(), af::afHost);
行优先Eigen矩阵转换
如果Eigen矩阵是行优先存储(如指定Eigen::RowMajor),需先转置为列优先布局再转换,避免数据布局不匹配导致的逻辑错误:
// 行优先Eigen矩阵 Eigen::Matrix<float, 3, 3, Eigen::RowMajor> eigen_row_mat; eigen_row_mat << 1, 2, 3, 4, 5, 6, 7, 8, 9; // 方式1:转置Eigen矩阵后转换 af::array af_mat(eigen_row_mat.cols(), eigen_row_mat.rows(), eigen_row_mat.transpose().data(), af::afHost); // 方式2:转换后转置ArrayFire数组(效果一致) af::array af_mat_row = af::transpose(af::array(eigen_row_mat.rows(), eigen_row_mat.cols(), eigen_row_mat.data(), af::afHost));
2. ArrayFire 转 Eigen
通过ArrayFire的host()方法将设备端数据拷贝到主机内存,再用Eigen的Map或直接内存拷贝完成转换:
方法1:使用Eigen::Map(零拷贝/可选拷贝)
Eigen::Map可直接包装主机内存指针,若需要独立的Eigen矩阵,直接赋值即可完成数据拷贝:
// 初始化ArrayFire数组 af::array af_mat = af::randu(3, 3, f32); // 零拷贝包装(注意:host()返回的指针生命周期由ArrayFire管理,长期使用建议拷贝) Eigen::Map<Eigen::MatrixXf> eigen_map(af_mat.host<float>(), af_mat.dims(0), af_mat.dims(1)); // 拷贝为独立的Eigen矩阵 Eigen::MatrixXf eigen_mat = eigen_map;
方法2:内存拷贝(更安全的内存管理)
用std::vector托管主机内存,再传递给Eigen矩阵,避免手动管理内存的风险:
af::array af_mat = af::randu(3, 3, f64); // double类型ArrayFire数组 // 分配主机内存并拷贝设备数据 std::vector<double> host_data(af_mat.elements()); af_mat.host(host_data.data()); // 初始化Eigen矩阵并拷贝数据 Eigen::MatrixXd eigen_mat(af_mat.dims(0), af_mat.dims(1)); std::memcpy(eigen_mat.data(), host_data.data(), af_mat.elements() * sizeof(double));
行优先ArrayFire视图转换
如果ArrayFire数组是行优先视图(如af::transpose返回的视图),可直接用Eigen的行优先矩阵匹配布局:
af::array af_mat = af::randu(3, 3, f32); af::array af_row_view = af::transpose(af_mat); // 行优先逻辑视图 std::vector<float> host_data(af_row_view.elements()); af_row_view.host(host_data.data()); // 构造Eigen行优先矩阵 Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> eigen_row_mat(af_row_view.dims(0), af_row_view.dims(1)); std::memcpy(eigen_row_mat.data(), host_data.data(), sizeof(float)*af_row_view.elements());
注意事项
- 确保数据类型匹配:ArrayFire的
f32对应Eigen的float,f64对应double,s32对应int等。 - ArrayFire的
host()方法会触发设备到主机的数据拷贝,频繁转换会影响性能,建议仅在必要时进行转换。 - 若Eigen矩阵非连续存储(如切片后的子矩阵),需先调用
eval()或matrix()获取连续内存后再转换。
内容的提问来源于stack exchange,提问作者E_1996
相关产品推荐
相关产品推荐

