C ++ 11 vector <bool>性能问题(带代码示例)

时间:2016-04-29 07:52:35

标签: c++ performance c++11 vector bitvector

我注意到在运行以下代码时,向量比bool数组慢得多。

TASK [Installation of <application_name>] ************************************************
task path: /var/lib/awx/projects/tests/<file>.yml:6
fatal: [xxx.163.xxx.69]: FAILED! => {"changed": false, "failed": true, "rc": 1, "stderr": "", "stdout": "", "stdout_lines": []}

NO MORE HOSTS LEFT *************************************************************
 [ERROR]: Could not create retry file '<file>_bat.retry'. The error was: [Errno
13] Permission denied: '<file>_bat.retry'

我能采取哪些方法让int main() { int count = 0; int n = 1500000; // slower with c++ vector<bool> /*vector<bool> isPrime; isPrime.reserve(n); isPrime.assign(n, true); */ // faster with bool array bool* isPrime = new bool[n]; for (int i = 0; i < n; ++i) isPrime[i] = true; for (int i = 2; i< n; ++i) { if (isPrime[i]) count++; for (int j =2; i*j < n; ++j ) isPrime[i*j] = false; } cout << count << endl; return 0; } 更快?顺便说一句,vector<bool>std::vector::push_back都比std::vector::emplace_back慢。

3 个答案:

答案 0 :(得分:14)

std::vector<bool>可能会遇到各种性能问题(例如,请查看https://isocpp.org/blog/2012/11/on-vectorbool)。

一般来说,你可以:

  • 使用std::vector<std::uint8_t>代替std::vector<bool>(也尝试std::valarray<bool>)。

    这需要更多的内存并且对缓存不太友好,但是没有开销(以位操作的形式)来访问单个值,因此在某些情况下它可以更好地工作(毕竟它就像你的数组bool,但没有内存管理的麻烦)

  • 如果您在编译时知道布尔数组的大小(或者至少可以建立一个合理的上限),请使用std::bitset
  • 如果Boost是一个选项,请尝试boost::dynamic_bitset(可以在运行时指定大小)

但是对于速度优化,你必须测试......

通过您的具体示例,我可以仅在关闭优化时确认性能差异(当然这不是可行的方法)。

在英特尔至强系统(-O3优化级别)上使用g ++ v4.8.3和clang ++ v3.4.5进行的一些测试给出了不同的图片:

                    time (ms)
                 G++      CLANG++
array of bool    3103     3010
vector<bool>     2835     2420    // not bad!
vector<char>     3136     3031    // same as array of bool
bitset           2742     2388    // marginally better

(答案中100次运行代码的时间已过去)

std::vector<bool>看起来不那么糟糕(源代码here)。

答案 1 :(得分:10)

vector<bool>可能具有模板特化,可以使用位数组来实现以节省空间。提取并保存一点并将其从/转换为bool可能会导致您观察到的性能下降。如果您使用std::vector::push_back,则会调整向量的大小,从而导致性能下降。下一个性能杀手可能是assign(最差复杂性:第一个参数的线性),而是使用operator [](复杂性:常量)。

另一方面,bool []保证为bool的数组。

您应该调整为n而不是n-1以避免未定义的行为。

答案 2 :(得分:5)

vector<bool> 可以高性能,但不是必须的。要使vector<bool>有效,它需要一次操作许多bool(例如isPrime.assign(n, true)),,实现者必须对其进行爱护。将单个bool索引为vector<bool>的速度很慢。

这是一个使用vector<bool>和clang + libc ++(libc ++部分很重要)的一段时间的主要发现者:

#include <algorithm>
#include <chrono>
#include <iostream>
#include <vector>

std::vector<bool>
init_primes()
{
    std::vector<bool> primes(0x80000000, true);
    primes[0] = false;
    primes[1] = false;
    const auto pb = primes.begin();
    const auto pe = primes.end();
    const auto sz = primes.size();
    size_t i = 2;
    while (true)
    {
        size_t j = i*i;
        if (j >= sz)
            break;
        do
        {
            primes[j] = false;
            j += i;
        } while (j < sz);
        i = std::find(pb + (i+1), pe, true) - pb;
    }
    return primes;
}

int
main()
{
    using namespace std::chrono;
    using dsec = duration<double>;
    auto t0 = steady_clock::now();
    auto p = init_primes();
    auto t1 = steady_clock::now();
    std::cout << dsec(t1-t0).count() << "\n";
}

这在大约28s(-O3)中为我执行。当我将其更改为返回vector<char>时,执行时间会上升到大约44秒。

如果你使用其他一些std :: lib运行它,你可能不会看到这种趋势。在libc ++上,std::find等算法已经过优化,可以一次搜索一个字位,而不是一次搜索一位。

有关供应商可以优化哪些std算法的更多详细信息,请参阅http://howardhinnant.github.io/onvectorbool.html