处理特征中两种存储布局的固定大小矩阵的连续向量

Dealing with a contiguous vector of fixed-size matrices for both storage layouts in Eigen

本文关键字:向量 连续 特征 两种 存储 布局 处理      更新时间:2023-10-16

外部库为我提供了一个原始指针,其中包含要映射到特征类型的doubles。从逻辑上讲,原始数组是小型密集固定大小矩阵的大有序集合,所有矩阵的大小都相同。主要问题是小的密集矩阵可能是行主排序或列主排序,我想同时容纳它们。

我目前的做法如下。请注意,小型固定大小块(在块数组中(的所有条目都需要在内存中连续。

template<int bs, class Mattype>
void block_operation(double *const vals, const int numblocks)
{
Eigen::Map<Mattype> mappedvals(vals, 
Mattype::IsRowMajor ? numblocks*bs : bs,
Mattype::IsRowMajor ? bs : numblocks*bs
);
for(int i = 0; i < numblocks; i++)
if(Mattype::isRowMajor)
mappedvals.template block<bs,bs>(i*bs,0) = block_operation_rowmajor(mappedvals);
else
mappedvals.template block<bs,bs>(0,i*bs) = block_operation_colmajor(mappedvals);
}

调用函数首先计算出 Mattype(从 2 个选项中(,然后使用正确的模板参数调用上述函数。

因此,我所有的算法都需要编写两次,并且我的代码穿插在这些布局检查中。有没有办法以与布局无关的方式做到这一点?请记住,此代码需要尽可能快。

理想情况下,我只会Map一次数据,并将其用于所需的所有操作。但是,我能想到的唯一解决方案是在我需要访问块时为每个小块调用一次 Map 构造函数。

template<int bs, StorageOptions layout>
inline Map<Matrix<double,bs,bs,layout>> extractBlock(double *const vals, 
const int bindex)
{
return Map<Matrix<double,bs,bs,layout>>(vals+bindex*bs*bs);
}

这个函数是否会被优化为零(通过像 GCC 7.3 或 Intel 2017 这样的现代编译器在-std=c++14 -O3下(,还是每次调用这个函数时我都会支付一小笔罚款(每个块一次,并且有很多小块(?有没有更好的方法可以做到这一点?

你的extractBlock很好,一个更简单但有点丑陋的解决方案是在block_operation开始时使用重新解释转换:

using BlockType = Matrix<double,bs,bs,layout|DontAlign>;
BlockType* blocks = reinterpret_cast<BlockType*>(vals);
for(int i...)
block[i] = ...;

这仅适用于固定大小的矩阵。还要注意DontAlign这很重要,除非您可以保证vals在 16 甚至 32 字节上对齐,具体取决于 AVX 和bs的存在......所以只需使用DontAlign