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% 的处理器能力。我在这里错过了什么吗?

4

2 回答 2

9

在 Windows 上,CRT 使用内置的 Windows 堆实现,它是单线程的。

HeapAlloc在分配期间锁定一个 CriticalSection(本质上是一个互斥体),本质上是对分配过程进行排序。

由于向量大小调整主要是堆(重新)分配,因此并行化它不会有太大改进。

当两个或多个线程尝试同时从同一个堆中分配或释放块时,序列化可确保互斥。

设置该HEAP_NO_SERIALIZE值可消除堆上的互斥。如果没有序列化,使用相同堆句柄的两个或多个线程可能会尝试同时分配或释放内存,这可能会导致堆损坏。

要从并行内存分配中受益,请使用不同的堆分配器。例如jemalloc

于 2019-02-07T15:33:12.280 回答
0

也许不是您正在寻找的答案,但您是否考虑过使用 boost::multi_array

于 2019-02-08T02:43:50.243 回答