为什么bool [] []比vector <vector <bool>&gt;更有效?

时间:2017-11-01 04:11:37

标签: c++ arrays c++11 vector stdvector

我正在尝试解决DP问题,我创建了一个2D数组,并一直填充2D数组。使用不同的测试用例多次调用我的函数。当我使用矢量&gt;时,我得到超出时间限制的错误(所有测试用例需要超过2秒)。但是,当我使用bool [] []时,花费更少的时间(大约0.33秒),我得到一个通行证。

有人可以帮我理解为什么会有矢量&gt;效率低于bool [] []。

bool findSubsetSum(const vector<uint32_t> &input)
{
    uint32_t sum = 0;

    for (uint32_t i : input)
        sum += i;

    if ((sum % 2) == 1)
        return false;

    sum /= 2;

#if 1
    bool subsum[input.size()+1][sum+1];
    uint32_t m = input.size()+1;
    uint32_t n = sum+1;

    for (uint32_t i = 0; i < m; ++i)
        subsum[i][0] = true;

    for (uint32_t j = 1; j < n; ++j)
        subsum[0][j] = false;

    for (uint32_t i = 1; i < m; ++i) {
        for (uint32_t j = 1; j < n; ++j) {

            if (j < input[i-1])
                subsum[i][j] = subsum[i-1][j];
            else
                subsum[i][j] = subsum[i-1][j] || subsum[i-1][j - input[i-1]];
        }
    }

    return subsum[m-1][n-1];
#else
    vector<vector<bool>> subsum(input.size()+1, vector<bool>(sum+1));

    for (uint32_t i = 0; i < subsum.size(); ++i)
        subsum[i][0] = true;

    for (uint32_t j = 1; j < subsum[0].size(); ++j)
        subsum[0][j] = false;

    for (uint32_t i = 1; i < subsum.size(); ++i) {
        for (uint32_t j = 1; j < subsum[0].size(); ++j) {

            if (j < input[i-1])
                subsum[i][j] = subsum[i-1][j];
            else
                subsum[i][j] = subsum[i-1][j] || subsum[i-1][j - input[i-1]];
        }
    }

    return subsum.back().back();
#endif
}

谢谢你, 艾哈迈德。

3 个答案:

答案 0 :(得分:0)

如果你需要一个矩阵并且你需要做高性能的东西,它并不总是使用嵌套std::vectorstd::array的最佳解决方案,因为它们在内存中不是连续的。不连续的内存访问会导致更高的缓存未命中。

查看更多:

std::vector and contiguous memory of multidimensional arrays

Is the data in nested std::arrays guaranteed to be contiguous?

另一方面,bool twoDAr[M][N]被保证是连续的。它确保减少缓存未命中。

查看更多:

C / C++ MultiDimensional Array Internals

了解缓存友好代码:

What is “cache-friendly” code?

答案 1 :(得分:0)

  

有人可以帮我理解为什么会有矢量&gt;再少一点   效率高于bool [] []。

二维bool数组实际上只是一个大的 M * N 的大型一维bool数组,没有间隙项目之间。

二维std::vector不存在;不仅仅是一个大的一维std::vector,而是一个std::vector的{​​{1}}。外部矢量本身没有记忆间隙,但在各个矢量的内容区域之间可能存在间隙。这取决于你的编译器如何实现非常特殊的std::vector<bool>类,但如果你的元素数量足够大,那么动态分配是不可避免的,以防止堆栈溢出,而这仅仅意味着指向分离的内存区域。

一旦您需要从分离的内存区域访问数据,事情就会变慢。

这是一个可能的解决方案:

  1. 尝试使用大小为std::vector的{​​{1}}。
  2. 如果无法加快速度,请使用std::vector<bool>大小(input.size() + 1) * (sum + 1)来避免模板专精化,并根据需要将元素转换为std::vector<char>

答案 2 :(得分:-1)

如果从一开始就你知道数组的输入大小,使用数组总是Vector或更快。因为vector是数组的包装器,所以是更高级的实现。它的好处是在需要时为您分配额外的空间,如果您有固定大小的元素,则不需要这些空间。

如果您在需要1D阵列的地方遇到问题,那么差异可能不会让您感到困扰(您拥有单个矢量和单个阵列)。但是创建一个2D数组,您还可以创建vector类的多个实例,因此arrayvector之间的时差乘以元素数量你的容器里有你的代码很慢。

这个时差背后有许多原因,但最明显的原因当然是调用vector 构造函数。您正在调用函数subsum.size()次。其他答案提到的记忆问题是另一个原因。

为了提高性能,建议您在代码中尽可能使用array。即使您需要使用vector,也应该尽量减少向量完成的重新调整大小的数量(保留,预分配),从而实现对array的更紧密的实现。