【问题标题】:Why vector<int> is faster than vector<bool> in the following case为什么在以下情况下 vector<int> 比 vector<bool> 快
【发布时间】:2015-09-28 10:45:43
【问题描述】:

这个现象是我在编写 LeetCode 问题N-Queens时发现的。

我有两个版本的可接受代码,唯一的区别是我存储哈希表的方式,一个是使用vector&lt;int&gt;,另一个是使用vector&lt;bool&gt;。具体来说,两个版本的代码如下:

版本 1,vector&lt;int&gt;,运行时间:4 毫秒
class Solution {
public:
void dfs(vector<string>& crtrst, vector<vector<string>>& finalrsts, int row, vector<int>& mup, vector<int>& m45dgr, vector<int>& m135dgr)
{
    int n = crtrst.size();
    
    if (row == n)
    {
        finalrsts.push_back(crtrst);
        return;
    }
    
    for (int j=0; j<n; j++)
    {
        if (mup[j] && m45dgr[j-row+n-1] && m135dgr[row+j])
        {
            crtrst[row][j] = 'Q';
            mup[j] = m45dgr[j-row+n-1] = m135dgr[row+j] = 0;
        
            dfs(crtrst,finalrsts,row+1,mup,m45dgr,m135dgr);
        
            crtrst[row][j] = '.';
            mup[j] = m45dgr[j-row+n-1] = m135dgr[row+j] = 1;
        }
    }
}

vector<vector<string>> solveNQueens(int n) 
{
    vector<vector<string>> finalrsts;
    vector<string> crtrst(n,string(n,'.'));
    vector<int> mup(n,1);
    vector<int> m45dgr(2*n-1,1); // degree 45: '\'
    vector<int> m135dgr(2*n-1,1); // degree 135: '/';
    int row = 0;
    dfs(crtrst,finalrsts,row,mup,m45dgr,m135dgr);
    return finalrsts;
}
};
版本 2,vector&lt;bool&gt;,运行时间:12 毫秒
class Solution {
public:
void dfs(vector<string>& crtrst, vector<vector<string>>& finalrsts, int row, 
    vector<bool>& mup, vector<bool>& m45dgr, vector<bool>& m135dgr)
{
    int n = crtrst.size();
    
    if (row == n)
    {
        finalrsts.push_back(crtrst);
        return;
    }
    
    for (int j=0; j<n; j++)
    {
        if (mup[j] && m45dgr[j-row+n-1] && m135dgr[row+j])
        {
            crtrst[row][j] = 'Q';
            mup[j] = m45dgr[j-row+n-1] = m135dgr[row+j] = false;
        
            dfs(crtrst,finalrsts,row+1,mup,m45dgr,m135dgr);
        
            crtrst[row][j] = '.';
            mup[j] = m45dgr[j-row+n-1] = m135dgr[row+j] = true;
        }
    }
}

vector<vector<string>> solveNQueens(int n) 
{
    vector<vector<string>> finalrsts;
    vector<string> crtrst(n,string(n,'.'));
    vector<bool> mup(n,true);
    vector<bool> m45dgr(2*n-1,true); // degree 45: '\'
    vector<bool> m135dgr(2*n-1,true); // degree 135: '/';
    int row = 0;
    dfs(crtrst,finalrsts,row,mup,m45dgr,m135dgr);
    return finalrsts;
}
};

据我所知,vector&lt;bool&gt; 使用 1 位而不是 bool 变量(可能是 2 字节)存储每个元素,vector&lt;int&gt; 使用 4 字节存储每个元素。所以vector&lt;bool&gt; 似乎比vector&lt;int&gt; 更小。但是,为什么比vector&lt;int&gt;慢呢?

【问题讨论】:

  • 直观地说,从压缩存储中打包/解包需要 时间,所以我预计 std::vector&lt;int&gt; 的表现优于std::vector&lt;bool&gt;,特别是因为 CPU 实际使用的是寄存器(int-sized 或更大)。
  • 请问您使用的是哪种编译器?
  • 这是一个很好的例子,说明程序员的直觉在预测性能行为时经常出错。
  • @DawidPi,我根据 LeetCode Online Judge 报了时间。所以我不知道它使用什么编译器。

标签: c++ vector


【解决方案1】:

访问单个位通常比访问完整的可寻址单元(C++ 术语中的字节)慢。例如,要写入一个字节,您只需发出一条写入指令(x86 上的 mov)。要写入位,您需要加载包含它的字节,使用位运算符设置字节内的正确位,然后存储结果字节。

位向量的紧凑尺寸非常适合存储需求,但它会导致速度变慢,除非您的数据变得足够大以至于缓存问题发挥作用。

如果您想获得速度并且仍然比每个值 4 字节更有效,请尝试vector&lt;unsigned char&gt;

【讨论】:

  • 为什么 vector&lt;unsigned char&gt; 会比 vector&lt;bool&gt; 快?我用我的桌面测试了差异(unsigned charbool 都被评估为 1 byte ),vector&lt;bool&gt; 的结果比vector&lt;unsigned char&gt; 慢 3 倍。我无法弄清楚细节,因为它们都是 1 字节。
  • 不,他们不是。具体来说,vector&lt;bool&gt; 不会将每个布尔值存储为单独的字节;相反,它将它们作为位打包在一起。这使其存储效率更高,但速度更慢。这就是问题的全部意义所在。
【解决方案2】:

我的解释:

vector&lt;type&gt; 专门用于bool,这是一个位图;这在存储方面效率很高(向量存储的 1Byte = 8 bool),但在实际访问数据时更差;对于任何其他vector,您可以通过*([address of first element + n * sizeof(element)]) 访问位于nth 位置的元素,但是为了获得bool-out-of-byte 存储,您将不可避免地需要进行一些位操作,在大缓存的情况下,这可能比仅拥有一组 ints 慢得多,每个数组代表一个真值。

【讨论】:

    猜你喜欢
    • 2023-01-20
    • 1970-01-01
    • 2019-08-22
    • 1970-01-01
    • 2011-04-20
    • 1970-01-01
    • 1970-01-01
    • 2014-10-24
    • 2021-11-07
    相关资源
    最近更新 更多