【发布时间】:2014-04-16 18:29:14
【问题描述】:
这个问题比较模糊,我真的需要回答它,但我很好奇答案可能是什么,所以我还是会问它。
我有一个生成大量矩阵的算法。它稍后会在其上运行第二个算法,该算法会生成一个解决方案。我运行了 100 次,平均耗时约 17 秒。
第二种算法几乎完全相同,唯一的区别是,第二种算法在每个矩阵生成后立即运行,因此它们实际上不需要存储在任何地方。这个变体显然需要更少的空间,这就是我制作它的原因,但对于同样的问题,它也只需要平均约 2 秒。
我没想到它会跑得更快,尤其是没有那么快。
代码相当大,所以我会尝试用类似伪代码的东西来概述区别:
recursiveFill(vector<Matrix> &cache, Matrix permutation) {
while(!stopCondition) {
// generate next matrix from current permutation
if(success)
cache.push_back(permutation);
else
recursiveFill(cache, permutation);
// some more code
}
}
recursiveCheck(Matrix permutation) {
while(!stopCondition) {
// alter the matrix some
if(success)
checkAlgorithm(permutation);
else
recursiveCheck(permutation);
// some more code
}
}
在递归填充之后,循环对缓存中的所有元素运行 checkAlgorithm。我没有包含在代码中的所有内容在两种算法中都是相同的。我猜想向量中的存储一直在消耗,但如果我没记错的话,每次过度填充时,c++ 向量的大小都会翻倍,因此重新分配不应该经常发生。 有什么想法吗?
【问题讨论】:
-
是的,不知道你在问什么。然而,std::vector 的开销不仅仅是在数组被重新调整大小并因此被复制时(尽管这会影响它),而且你的元素必须是可复制的,甚至可以使用 std::vector,所以除非你'正在存储指针或引用,您会将完整的深层副本推入向量中。
-
cachegrind(valgrind的缓存检查工具,你通过在命令行中添加--tool=cachegrind来激活它)对你的两个代码说什么? -
这真的取决于实现。我猜你不仅会产生缓存未命中,还会产生页表未命中,其中操作系统被颠簸以不断地来回转换虚拟地址,因为第一个中的递归调用是不同的,顺序比少
-
什么是
Matrix?它使用堆分配吗?它是可移动的(并且您的编译器是否支持移动语义)?交换是否正确重载并有效实施?
标签: c++ performance vector benchmarking