并行向量调整大小并没有加速

4

我有8个处理器可供使用。 我想进行以下并行调整大小:

    vector<vector <int> > test;
    test.resize(10000);
    #pragma omp parallel num_threads(8)
    {
        #pragma omp for
        for (int i = 0;i < 10000;i++)test[i].resize(500000);
    }

我注意到这个程序没有使用100%的处理器性能,而只使用了15%。当我修改代码时,

    vector<vector <int> > test;
    test.resize(1000000);
    #pragma omp parallel num_threads(8)
    {
        #pragma omp for
        for (int i = 0;i < 1000000;i++)test[i].resize(5000);
    }

该程序使用了约60%的处理器资源。我不明白这种现象——在两种情况下,我希望它会使用100%的处理器资源。我是否有所遗漏?


你的操作系统是什么? - rustyx
操作系统是Windows 10。 - piotrmizerka
1
如果您执行的操作比重新分配向量更加CPU密集,行为是否会发生变化?换句话说,这是您使用工具的问题,还是您的工作负载并不太适合八路并行处理? - Willis Blackburn
1
分配的内部可能需要同步。分配可能不受 CPU 的限制,... - Jarod42
你肯定会遇到内存系统带宽问题,这样的比较实际用途很小。如果你想通过缩短向量来获得缓存性能的指示,那么需要进行更多的研究,而我不愿意承担这个任务。 - tim18
2个回答

9
在Windows上,CRT使用内置的Windows堆实现,这是单线程的。 HeapAlloc会在分配期间锁定CriticalSection(本质上是互斥量),从而使分配过程串行化。
由于向量调整大小大多是堆(重新)分配,因此并行化不会带来太多改进。
序列化确保在两个或更多线程尝试同时从同一堆中分配或释放块时进行互斥。将HEAP_NO_SERIALIZE值设置为消除对堆的互斥操作。没有序列化,使用相同堆句柄的两个或多个线程可能会尝试同时分配或释放内存,可能会导致堆损坏。
要从并行内存分配中受益,请使用不同的堆分配器。例如jemalloc

2
我相信Linux上的glibc默认使用线程感知的分配器。;-) - Omnifarious
2
没错,FreeBSD使用jemalloc :) - rustyx

0

也许不是你想要的答案,但你考虑过使用boost::multi_array吗?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接