将特征矩阵的向量设置为 0

Set Vector of Eigen Matrices to 0

我正在为一个特殊的应用调整霍夫变换,为此我需要在一个向量中存储很多特征矩阵,并且我需要它们在开始时都为 0。 这就是我初始化它的方式:

typedef Eigen::Matrix<int,30,150> HoughMatrix
std::vector<HoughMatrix> hough_spaces(num_spaces)

我现在的问题是,使所有这些矩阵的所有元素都等于 0 的最快方法是什么? 我尝试遍历每个 Vector 元素并执行:

hough_spaces[i].setZero()

但这相当慢。有没有更快的方法?或者直接将它们初始化为0的方法? 感谢您的帮助

有趣的是 Eigen::Matrix 似乎没有构造函数来初始化元素。来自 Eigen: The Matrix class:

Matrix3f a;

-> 没有分配,没有元素初始化

MatrixXf a(10,15);

-> 已分配但未初始化的元素

最后 (!) 一些允许为小型向量初始化元素的构造函数:

Vector2d a(5.0, 6.0);
Vector3d b(5.0, 6.0, 7.0);
Vector4d c(5.0, 6.0, 7.0, 8.0);

如果您继续阅读 Eigen: Advanced initialization,您会发现

Special matrices and arrays

The Matrix and Array classes have static methods like Zero(), which can be used to initialize all coefficients to zero. [...]

Example

std::cout << "A fixed-size array:\n";
Array33f a1 = Array33f::Zero();
std::cout << a1 << "\n\n";

PS

But that was rather slow. Is there a faster way?

如果不了解有关 "slow" 的 exaclt 含义的更多详细信息,则很难讨论细节。我只能说我希望初始化只比分配单元化元素快,然后 setZero().

首先,Eigen::Matrix<int,30,150> 默认对齐到 16 字节,这在 64 位系统或 C++17 上很可能会正常工作,但否则您可能会遇到 some caveats。 解决任何对齐问题的简单方法是编写

typedef Eigen::Matrix<int,30,150, Eigen::DontAlign> HoughMatrix;

现在写你想要的东西的惯用方式是写

std::vector<HoughMatrix> hough_spaces(num_spaces, HoughMatrix::Zero());

但是,这将导致 memcpy 调用循环(至少对于 gcc 和 clang:https://godbolt.org/z/ULixBm)。

或者,您可以创建一个包含未初始化 HoughMatrixes 的向量并在其上应用 std::memset

std::vector<HoughMatrix> hough_spaces(num_spaces);
std::memset(hough_spaces.data(), 0, num_spaces*sizeof(HoughMatrix));

请注意,为了 运行 而 Eigen 不必循环遍历所有元素,需要 HoughMatrix 未对齐(如开头所示)或禁用对齐断言:https://godbolt.org/z/nDJqV5

如果您实际上不需要 std::vector 功能(主要是复制和调整大小的能力),您可以在使用后使用 callocfree 分配一些内存.为了防漏,可以将其封装成 std::unique_ptr:

// unique_ptr with custom deallocator (use a typedef, if you need this more often):
std::unique_ptr<HoughMatrix[], void(&)(void*)> hough_spaces(static_cast<HoughMatrix*>(std::calloc(num_spaces, sizeof(HoughMatrix))), std::free);
if(!hough_spaces) throw std::bad_alloc(); // Useful, if you actually handle bad-allocs. If you ignore failed callocs, you'll likely segfault when accessing the data.

Clang 和 gcc 会将其优化为单个 calloc/free 对: https://godbolt.org/z/m4rzRq


一种完全不同的方法是尝试使用 3D 张量而不是矩阵向量:

typedef Eigen::Tensor<int, 3> HoughSpace;
HoughSpace hough_spaces(num_spaces,30,150);
hough_spaces.setZero();

看看 generated assembly 这看起来是半最优的,即使 -O3 -DNDEBUG


总的来说,请注意,对任何与内存相关的内容进行基准测试可能会产生误导。例如,对 calloc 的调用可能 return 几乎是瞬时的,但在较低级别上指向未分配的页面,这使得第一次访问它们的实际成本更高。