我有这个序列号:
std::vector<T> input, output;
//populate input
for (size_t i=0 ; i < input.size() ; i++){
output.push_back(//something using input[i]);
}
请注意,使用output[i]
计算input[i]
至关重要。现在我想并行化它。一个简单的解决方案是:
std::vector<T> input, output;
//populate input
#pragma omp for schedule(dynamic) ordered
for (size_t i=0 ; i < input.size() ; i++){
#pragma omp ordered
output.push_back(//something using input[i]);
}
然而,这可能是非常低效的(ordered
需要获得锁定,如果执行多次会产生很大的开销,此外如果块大小很小,则会产生更多的开销)。另一种可能的解决方案是分别填充每个块,然后合并它们(以有序的方式):
std::vector<T> input, output;
//populate input
#pragma omp parallel
{
std::vector<T> myOutput;
std::vector<int> myIndexes;
#pragma omp for schedule(static,1) //NOTICE STATIC!
for (size_t i=0 ; i < input.size() ; i++){
myOutput.push_back(//something using input[i]);
myIndexes.push_back[i];
}
#pragma omp for ordered schedule(static)
for(int i=0 ; i<omp_get_num_threads() ; i++){
#pragma omp ordered
{
std::cout<<"Hello from thread "<<omp_get_thread_num()<<": ";
for(size_t j = 0; j < myIndexes.size(); j++)
std::cout<<indexes[j]<<" ";
std::cout<<std::endl;
}
}
}
假设input.size()=10
我们有8个核心。这就是我想要打印的内容:
Hello from thread 0: 0 1
Hello from thread 1: 2 3
Hello from thread 2: 4
Hello from thread 3: 5
Hello from thread 4: 6
Hello from thread 5: 7
Hello from thread 6: 8
Hello from thread 7: 9
但是这个是它实际印刷的内容:
Hello from thread 0: 0 8
Hello from thread 1: 1 9
Hello from thread 2: 2
Hello from thread 3: 3
Hello from thread 4: 4
Hello from thread 5: 5
Hello from thread 6: 6
Hello from thread 7: 7
this问题中的代码可以解决我的问题,但这有点作弊(它实际上并没有使用#pragma omp parallel for
)。
是否可以仅使用openmp获得我想要的行为?
答案 0 :(得分:1)
最简单的解决方案是使用operator[]
代替push_back
。
std::vector<T> input, output;
//populate input
output.resize(input.size())
#pragma omp parallel for
for (size_t i=0 ; i < input.size() ; i++){
output[i] = //something using input[i]);
}
现在假设T
是 DefaultInsertable 。如果没有,您可以使用resize
的特定虚拟值参数。
BTW:我不明白你的预期输出。为什么您希望索引在不同的线程上多次出现?
编辑:
OpenMP规范清楚地说明了static
调度(表2.5)。
分配了块 团队中的线程以线程的顺序循环方式 号。
所以实际结果是符合的。