这是一个允许并行插入/删除列表的新元素的解决方案。
对于带有N 元素的列表,我们首先将列表切割成nthreads 列表
大约有N/nthreads 元素。在并行区域中,可以这样完成
int ithread = omp_get_thread_num();
int nthreads = omp_get_num_threads();
int t0 = (ithread+0)*N/nthreads;
int t1 = (ithread+1)*N/nthreads;
std::list<int> l2;
#pragma omp for ordered schedule(static)
for(int i=0; i<nthreads; i++) {
#pragma omp ordered
{
auto it0 = l.begin(), it1 = it0;
std::advance(it1, t1-t0);
l2.splice(l2.begin(), l2, it0, it1);
}
}
l2 是每个线程的切割清单。
然后我们可以并行处理每个列表。例如,我们可以像这样在列表中的每个第一个位置插入 -1
auto it = l2.begin();
for(int i=(t0+4)/5; i<(t1+4)/5; i++) {
std::advance(it, 5*i-t0);
l2.insert(it, -1);
}
最后,在我们对列表进行并行操作之后,我们将每个线程的列表拼接回一个列表,如下所示:
#pragma omp for ordered schedule(static)
for(int i=0; i<nthreads; i++) {
#pragma omp ordered
l.splice(l.end(), l, l2.begin(), l2.end());
}
算法本质上是。
- 通过列表顺序快速制作剪切列表。
- 并行处理切割清单添加、修改或删除元素。
- 将修改后的切割清单按顺序重新拼接在一起。
这是一个工作示例
#include <algorithm>
#include <iostream>
#include <list>
#include <omp.h>
int main(void) {
std::list<int> l;
for(int i=0; i<22; i++) {
l.push_back(i);
}
for (auto it = l.begin(); it != l.end(); ++it) {
std::cout << *it << " ";
} std::cout << std::endl;
int N = l.size();
#pragma omp parallel
{
int ithread = omp_get_thread_num();
int nthreads = omp_get_num_threads();
int t0 = (ithread+0)*N/nthreads;
int t1 = (ithread+1)*N/nthreads;
//cut list into nthreads lists with size=N/nthreads
std::list<int> l2;
#pragma omp for ordered schedule(static)
for(int i=0; i<nthreads; i++) {
#pragma omp ordered
{
auto it0 = l.begin(), it1 = it0;
std::advance(it1, t1-t0);
l2.splice(l2.begin(), l2, it0, it1);
}
}
//insert -1 every 5th postion
auto it = l2.begin();
for(int i=(t0+4)/5; i<(t1+4)/5; i++) {
std::advance(it, 5*i-t0);
l2.insert(it, -1);
}
//splice lists in order back together.
#pragma omp for ordered schedule(static)
for(int i=0; i<nthreads; i++) {
#pragma omp ordered
l.splice(l.end(), l, l2.begin(), l2.end());
}
}
for (auto it = l.begin(); it != l.end(); ++it) {
std::cout << *it << " ";
} std::cout << std::endl;
}
结果
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
-1 0 1 2 3 4 -1 5 6 7 8 9 -1 10 11 12 13 14 -1 15 16 17 18 19 -1 20 21