为什么维护排序数组比C ++中的Vector更快

时间:2013-07-03 15:13:44

标签: c++ performance optimization vector

我正在创建一个大小为100的数组和向量,并生成一个随机值,并尝试将数组和向量维护为已排序。 这是我的代码

vector<int> myVector;
int arr[SIZE];
clock_t start, finish;
int random;
for(int i=0; i<SIZE;i++)
{
    myVector.push_back(0);
    arr[i] = 0;
}
    //testing for Array
start = clock(); 
for(int i=0; i<MAX;++i)
{
    random = getRandom(); //returns rand() % 100
    for(int j=0; j<SIZE;++j){
        if(random > arr[j])
        {
            for(int k = SIZE - 1; k > j ; --k)
            {
                arr[k] = arr[k-1];
            }
            arr[j] = random;
            break;
        }
    }
}
finish = clock();
cout << "Array Time " << finish - start << endl;

//Vector Processing
start = clock();
for(int i=0; i<MAX;++i)
{
    random = getRandom(); //returns rand() % 100
    for(int j=0; j<SIZE;++j){
        if(random > myVector[j])
        {
            for(int k = SIZE - 1; k > j ; --k)
            {
                myVector[k] = myVector[k-1];
            }
            myVector[j] = random;
            break;
        }
    }
}
finish = clock();
cout << "Vector Time " << finish - start << endl;

输出如下:

数组时间:5

向量时间:83

在这种情况下,我无法理解为什么矢量与数组相比如此之慢? 这是否与优先使用Vector over Array的拇指规则相矛盾。

请帮助!

3 个答案:

答案 0 :(得分:4)

首先:编程中的许多经验法则都不是关于性能的几毫秒,而是关于管理复杂性,因此避免了错误。在这种情况下,它是关于执行范围检查,大多数矢量实现在调试模式下执行,而数组不执行。它也是关于动态数组的内存管理 - 矢量确实管理它的内存本身,而你必须在数组中手动​​执行它而存在引入内存泄漏的风险(忘记delete[]或使用delete而不是?我是你的!)。这是关于易用性,例如调整矢量大小或在中间插入元素,这对于手动管理的数组来说是繁琐的工作 换句话说,性能测量永远不会违反经验法则,因为经验法则从不针对性能。性能测量只能是遵守编码准则的几个可能原因之一。

乍一看,我猜你还没有启用优化。然后,向量性能损失的主要来源是索引检查,许多向量实现已启用调试版本。这些不会在优化的构建中发挥作用,因此这应该是您首先关注的问题。 经验法则:未启用优化的性能测量无意义

如果启用优化仍然可以为阵列显示更好的性能,那么还有另一个区别:

数组存储在堆栈中,因此编译器可以直接使用地址并在编译时计算地址偏移量,而向量元素存储在堆上,编译器必须取消引用存储在向量中的指针。我希望优化器一次取消引用指针并从该点计算地址偏移量。尽管如此,与编译时计算的地址偏移相比,可能会有一个小的性能损失,特别是如果优化器可以稍微展开循环。 这仍然与经验法则不矛盾,因为你在这里比较苹果和梨。经验法则说,

  

首选std::vector覆盖动态数组,而不是std::array覆盖已修复的数组。

因此要么使用动态分配的数组(包括某种delete[]),要么将固定大小的数组与std::array进行比较。在C ++ 14中,您将不得不考虑游戏中的新候选者,即std::dynarray和C ++ 14 VLA,不可调整大小的运行时长度数组,与C的VLA相当。

<强>更新 正如评论中指出的那样,优化器擅长识别没有副作用的代码,比如你从未读过的数组操作。 std::vector实现非常复杂,优化器通常无法通过这几个间接层看到并优化掉所有插入,因此与向量的某个时间相比,您将获得零时间。在循环之后读取数组将禁用这种粗鲁的优化。

答案 1 :(得分:-1)

向量类必须动态增长内存,这可能涉及不时复制整个内容。 它还必须为许多操作调用内部函数 - 比如重新分配。 它也可能具有边界检查等安全功能。

与此同时,您的阵列已预先分配,并且您的所有操作都不会调用任何内部函数。

这是更多功能的间接费用。

谁说在所有情况下矢量应该比数组更快? 你的数组不需要增长,这就是数组确实更快的特殊情况!

答案 2 :(得分:-3)

因为数组是本机数据类型,而编译器可以直接从内存中操作它,所以它们由编译的exec在内部管理。

另一方面,当我阅读时,你会得到更像是类,模板的向量,并且它需要通过另一个头文件和库进行管理。

基本上本机数据类型可以在不包含任何标题的情况下进行管理,这使得它们更容易从程序中操作,而无需使用外部代码。这使得向量时间的开销是程序需要查看代码并使用与向量数据类型相关的方法。

每次您需要向应用添加更多代码并通过它进行操作时,都会降低您的应用效果

您可以阅读相关内容,hereherehere