将特征矩阵的向量设置为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<int,30,150>将与16个字节对齐,这在64位系统或C++17中很可能正常工作,但您可能会面临一些警告。解决对齐问题的一个简单方法是编写

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();

从生成的程序集来看,即使使用-O3 -DNDEBUG,这看起来也是半最优的。


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

有趣的是,Eigen::Matrix似乎没有用于初始化元素的构造函数。来自特征:矩阵类:

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);

如果您继续阅读特征:高级初始化,您可以找到

特殊矩阵和数组

Matrix和Array类具有类似Zero((的静态方法可以用于将所有系数初始化为零。[…]

示例

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

PS

但这相当缓慢。有更快的路吗?

如果不知道"慢"是什么意思的更多细节,就很难讨论细节。我所能说的是,我希望初始化只比分配单元化元素和setZero()更快。

最新更新