【问题标题】:Why does my code slow down when i replace arrays with stl vectors, in c++, are arrays more faster than vectors?当我用 stl 向量替换数组时,为什么我的代码会变慢,在 c++ 中,数组比向量更快吗?
【发布时间】:2021-12-22 08:47:13
【问题描述】:

下面是我用来比较的代码:

// Example program
#include <iostream>
#include <string>
#include <vector>
#include <chrono>
using namespace std::chrono;
using namespace std;
            
bool existHelperArrayVersion(string &word, int i, int u_i, int u_j, vector<vector<char>>& Board)
{
    if(i>=word.length())
    {
        return true;
    }
    else
    {
        bool answer  = false;      
        if(Board[u_i][u_j] == word[i])
        {
            char temp             = Board[u_i][u_j];
            Board[u_i][u_j]       = '?';
            int row_len           = Board.size();  
            int col_len           = Board[0].size();

            // Uses Array
            int row_offset[4]={0,  0, 1, -1};
            int col_offset[4]={1, -1, 0,  0};
            
            for(int k=0; k<4; k++)
            {
                int v_i = u_i + row_offset[k];
                int v_j = u_j + col_offset[k];
                
                if( !(0 >v_i || v_i >= row_len || 0>v_j || v_j >= col_len)  && (Board[v_i][v_j] != '?'))
                    answer |= existHelperArrayVersion(word, i+1, v_i, v_j, Board);
            }
               
            if(i+1 == word.length())
                answer |= true;
            Board[u_i][u_j] = temp;
        }
        return answer;
    }
}

bool existHelperVectorVersion(string &word, int i, int u_i, int u_j, vector<vector<char>>& Board)
{
    if(i>=word.length())
    {
        return true;
    }
    else
    {
        bool answer  = false;
        if(Board[u_i][u_j] == word[i])
        {
            char temp             = Board[u_i][u_j];
            Board[u_i][u_j]       = '?';
            int row_len           = Board.size();  
            int col_len           = Board[0].size();

            //Uses Vectors
            vector<int> row_offset = {0,  0, 1, -1};
            vector<int> col_offset = {1, -1, 0,  0};
            
            for(int k=0; k<4; k++)
            {
                int v_i = u_i + row_offset[k];
                int v_j = u_j + col_offset[k];
                
                if( !(0 >v_i || v_i >= row_len || 0>v_j || v_j >= col_len)  && (Board[v_i][v_j] != '?'))
                    answer |= existHelperVectorVersion(word, i+1, v_i, v_j, Board);
            }
               
            if(i+1 == word.length())
                answer |= true;
            Board[u_i][u_j] = temp;
        }
        return answer;
    }
}

bool exist(vector<vector<char>>& board, string word, int option) 
{
    if(option == 0)
        cout << "----ARRAY------\n";
    else if(option == 1)
        cout << "---VECTOR-----\n";
        
    bool answer   = false;
    for(int i=0; i<board.size(); i++)
    {
        for(int j=0; j<board[i].size(); j++)
        {
            if(option == 0)
                answer |= existHelperArrayVersion( word, 0, i, j, board);
            else if(option == 1)
                answer |= existHelperVectorVersion( word, 0, i, j, board);
                
            if(answer)
            {
                return true;
            }
        }
    }
    return false;
}

int main()
{
    
    string word                 =   "AAAAAAAAAAAAAAB";
    vector<vector<char>> board  =   {{'A','A','A','A','A','A'},
                                     {'A','A','A','A','A','A'},
                                     {'A','A','A','A','A','A'},
                                     {'A','A','A','A','A','A'},
                                     {'A','A','A','A','A','A'},
                                     {'A','A','A','A','A','A'}};

    auto start    = high_resolution_clock::now();
    bool answer   = exist(board, word, 0);
    auto stop     = high_resolution_clock::now();
    auto duration = duration_cast<microseconds>(stop - start);
    cout << "Time taken when Using C-style Array : " << duration.count() << " microseconds" << endl;
    
    start         = high_resolution_clock::now();
    answer        = exist(board, word, 1);
    stop          = high_resolution_clock::now();
    duration      = duration_cast<microseconds>(stop - start);
    cout << "Time taken when Using STL vector    : " << duration.count() << " microseconds" << endl;
    
}

输出

----ARRAY------
Time taken when Using C-style Array : 112931 microseconds
---VECTOR-----
Time taken when Using STL vector    : 330641 microseconds

如您所见,我的函数的数组版本的执行速度平均比其向量版本快 3 倍。 (我多次运行它并得到类似的结果)
问:
与数组相比,向量真的那么慢吗?
我认为他们的表现应该是不相上下的。
这是我在在线环境中运行的 URL http://cpp.sh/2ubur

【问题讨论】:

  • 你是如何编译代码的?确保启用优化。衡量未优化的构建没有意义。
  • 您将int[4]std::vector&lt;int&gt; 进行比较。对于std::vector,这不是一个好的用例,因为大小是恒定的。更好的比较是将int[4]std::array&lt;int, 4&gt; 或将std::vector&lt;int&gt; 与动态分配的数组进行比较。
  • 你在vector&lt;int&gt; row_offset = {0, 0, 1, -1};vector&lt;int&gt; col_offset = {1, -1, 0, 0};这里实例化了一个新的向量。由于向量使用动态内存分配,它当然比分配本地原始数组要慢得多,后者或多或少在零时间内完成。
  • std::vector 不是也不能与普通数组或std::array 相提并论。简单的原因是它需要某种间接(即指针)来适应动态大小的变化。这反过来意味着为了使用向量的地址到达元素#3,您首先从向量中读取第一个元素的地址,然后前进三个元素。对于数组,数组的地址是第一个元素的地址。
  • 为了完整起见:任何时候你想到new T[count],你都应该想到vector&lt;T&gt;,这可能是你读到的(以某种形式)并在这里被误解了。

标签: c++ arrays performance heap-memory stdvector


【解决方案1】:
        vector<int> row_offset = {0,  0, 1, -1};
        vector<int> col_offset = {1, -1, 0,  0};

这会在每次调用函数时(几乎)导致 2 次堆数据分配。

        int row_offset[4]={0,  0, 1, -1};
        int col_offset[4]={1, -1, 0,  0};

这不会在每次调用函数时(几乎)导致 2 次堆数据分配。

std::vector&lt;int&gt; foo = {1,2,3} 在创建成本方面类似于 int* foo = new int[]{1,2,3},而不是 int foo[] = {1,2,3}

std::array<int, 3> foo={1,2,3}

是“包含数据的固定大小缓冲区”的标准库版本。 std::vector 是一个动态大小的缓冲区。

Here 是一个活生生的例子,我将std::vector 替换为std::array,并更改了C 数组版本以动态创建和销毁数组。您会注意到时间交换。

【讨论】:

  • 这很有意义。谢谢
【解决方案2】:

您在函数中创建向量,因此每个函数调用都会重新分配它们的内存并在函数结束时销毁它们。相反,一个数组会不断地嵌入到您的程序中。

尝试将向量移出函数,然后两个函数同样快:http://cpp.sh/53t2z

【讨论】:

    【解决方案3】:

    如果你替换:

      vector<int> row_offset = { 0,  0, 1, -1 };
      vector<int> col_offset = { 1, -1, 0,  0 };
    

    与:

      static vector<int> row_offset; row_offset  = { 0,  0, 1, -1 };
      static vector<int> col_offset; col_offset = { 1, -1, 0,  0 };
    

    差异会小得多。在第二个版本中,向量不会每次都从头开始构建。

    这仅用于演示目的,并非可效仿的示例。

    无论如何,这里最好的方法是用std::array 替换std::vector,因为这里有固定大小。

    顺便说一句,http://cpp.shstd::array 的版本似乎比原始数组版本更快。

    【讨论】:

    • 使这些向量保持不变,我认为它们没有被修改。另外,再次将它们设为std::arrays,因为它们没有被修改。详细说明一下:如果您不想修改它们并使它们保持不变,编译器会告诉您是否不小心修改了它们。更喜欢编译器错误而不是链接器错误,而不是运行时错误,而不是只在半夜发生在客户系统上的错误。 ;)
    • @UlrichEckhardt 这只是为了演示。这不是一个可以效仿的例子。我已经编辑了答案以明确这一点。
    猜你喜欢
    • 1970-01-01
    • 2013-05-09
    • 2012-12-03
    • 2023-04-06
    • 2022-08-03
    • 1970-01-01
    • 1970-01-01
    • 2011-07-31
    • 2012-01-31
    相关资源
    最近更新 更多