矢量VS阵列性能(Vector vs Array Performance)

2019-09-02 07:21发布

在另一个线程我开始了关于矢量和阵列,其中我主要是玩魔鬼代言人的讨论,推按钮。 然而,在此过程中,我无意中发现了有我有些纳闷的测试情况下,我想有一个关于它的真正的讨论,在“滥用”我得到了打魔鬼代言人,开始真正的在该线程的讨论现在是不可能的。 但是,具体的例子我很感兴趣,我可以把它圆满无法解释自己。

讨论的是矢量的VS阵列表现一般,忽略动态元素。 例如:明明矢量持续使用的push_back()会慢下来。 我们假设矢量和阵列的预先填充数据。 示例性I呈现,并且随后通过在线程的单个修饰的,是以下内容:

#include <iostream>
#include <vector>
#include <type_traits>
using namespace std;

const int ARRAY_SIZE = 500000000;

// http://stackoverflow.com/a/15975738/500104
template <class T>
class no_init_allocator
{
public:
    typedef T value_type;

    no_init_allocator() noexcept {}
    template <class U>
        no_init_allocator(const no_init_allocator<U>&) noexcept {}
    T* allocate(std::size_t n)
        {return static_cast<T*>(::operator new(n * sizeof(T)));}
    void deallocate(T* p, std::size_t) noexcept
        {::operator delete(static_cast<void*>(p));}
    template <class U>
        void construct(U*) noexcept
        {
            // libstdc++ doesn't know 'is_trivially_default_constructible', still has the old names
            static_assert(is_trivially_default_constructible<U>::value,
            "This allocator can only be used with trivally default constructible types");
        }
    template <class U, class A0, class... Args>
        void construct(U* up, A0&& a0, Args&&... args) noexcept
        {
            ::new(up) U(std::forward<A0>(a0), std::forward<Args>(args)...);
        }
};

int main() {
    srand(5);  //I use the same seed, we just need the random distribution.
    vector<char, no_init_allocator<char>> charArray(ARRAY_SIZE);
    //char* charArray = new char[ARRAY_SIZE];
    for(int i = 0; i < ARRAY_SIZE; i++) {
        charArray[i] = (char)((i%26) + 48) ;
    }

    for(int i = 0; i < ARRAY_SIZE; i++) {
        charArray[i] = charArray[rand() % ARRAY_SIZE];
    }
}

当我在我的机器上运行此,我得到以下端子输出。 在第一次运行是与矢量线路未注释,第二个是与所述阵列线注释。 我用优化的最高水平,给予矢量成功的最佳机会。 下面是我的结果,所述第一两个运行与阵列线取消注释,后两个与所述矢量线。

//Array run # 1
clang++ -std=c++11 -stdlib=libc++ -o3 some.cpp -o b.out && time ./b.out

real    0m20.287s
user    0m20.068s
sys 0m0.175s

//Array run # 2
clang++ -std=c++11 -stdlib=libc++ -o3 some.cpp -o b.out && time ./b.out

real    0m21.504s
user    0m21.267s
sys 0m0.192s

//Vector run # 1
clang++ -std=c++11 -stdlib=libc++ -o3 some.cpp -o b.out && time ./b.out

real    0m28.513s
user    0m28.292s
sys 0m0.178s

//Vector run # 2
clang++ -std=c++11 -stdlib=libc++ -o3 some.cpp -o b.out && time ./b.out

real    0m28.607s
user    0m28.391s
sys 0m0.178s

这阵列跑赢载体上的50%的订单让我惊讶的非常不但是让我感到吃惊的是,不同的是,我希望他们可以忽略不计,而且我觉得这个测试用例的性质我是模糊的性质的结果。 当您运行在数组的大小是小本测试中,性能差异显着消散。

我的解释:

矢量附加执行指令造成的向量指令在内存中对齐不佳,甚至在这个例子中,在对2个不同的“块”一个非常糟糕的点的拆分。 这是造成内存来回跳转缓存VS数据缓存VS指令缓存级别之间的频率要高于你期望的那样。 我也怀疑LLVM编译器可能会夸大弱点,并优化不佳,由于一些较新的C ++ 11种的元素,虽然我没有理由对任何假设,除了和猜想这些解释。

我很感兴趣,如果A:有人可以复制我的结果和B:如果某人有怎样的计算机运行的是这个特定的基准更好的解释,为什么载体是如此明显在这种情况下表现不佳的阵列。

我的设立: http://www.newegg.com/Product/Product.aspx?Item=N82E16834100226

Answer 1:

我可以保证,LLVM确实INFACT misoptimize的std ::向量(如果你实际上在所有优化),至少截至目前。 它不正确内联的许多功能的调用参与。 您将获得与GCC更好的性能。



Answer 2:

一个简单的解释:你禁用的优化构建。 你想-O3 ,不-o3

我没有可用于精确地再现您的测试铛,但我的结果如下:

//Array run # 1
$ g++ -std=c++11 -O3 test.cpp -o b.out && time ./b.out

real    0m25.323s
user    0m25.162s
sys 0m0.148s

//Vector run #1
$ g++ -std=c++11 -O3 test.cpp -o b.out && time ./b.out

real    0m25.634s
user    0m25.486s
sys 0m0.136s


文章来源: Vector vs Array Performance