我正在将Hough变换用于特殊应用,为此,我需要在向量中存储很多本征矩阵,并且一开始它们都必须为0。 这就是我初始化的方式:
typedef Eigen::Matrix<int,30,150> HoughMatrix
std::vector<HoughMatrix> hough_spaces(num_spaces)
我现在的问题是,使所有这些矩阵的所有元素等于0的最快方法是什么? 我尝试遍历每个Vector元素并执行以下操作:
hough_spaces[i].setZero()
但这太慢了。有没有更快的方法?还是直接将它们初始化为0的方法? 谢谢您的帮助
答案 0 :(得分:2)
首先,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)。
或者,您可以创建未初始化的HoughMatrix
的向量,并将std::memset
应用于它们:
std::vector<HoughMatrix> hough_spaces(num_spaces);
std::memset(hough_spaces.data(), 0, num_spaces*sizeof(HoughMatrix));
请注意,要在没有本征循环的情况下必须遍历所有元素,就必须使HoughMatrix
不对齐(如开头所示)或禁用对齐声明:https://godbolt.org/z/nDJqV5
如果实际上不需要std::vector
功能(主要是复制和调整大小的功能),则可以使用calloc
和free
在使用后分配一些内存。为了安全起见,可以将其封装到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
的情况下,看着generated assembly看起来也是半最佳的。
总体而言,请注意,对与内存相关的任何事物进行基准测试可能会产生误导。例如,对calloc
的调用可能几乎立即返回,但在较低级别上指向未分配的页面,这使得首次访问它们实际上更加昂贵。
答案 1 :(得分: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,则会发现
特殊矩阵和数组
Matrix和Array类具有静态方法,例如Zero(),该方法可以 可用于将所有系数初始化为零。 [...]
示例
std::cout << "A fixed-size array:\n"; Array33f a1 = Array33f::Zero(); std::cout << a1 << "\n\n";
PS
但这太慢了。有没有更快的方法?
尽管不了解“慢”意味着什么的更多细节,但很难讨论细节。我只能说,我希望初始化只会比分配单元化元素然后分配setZero()
更快。