【发布时间】:2012-10-23 16:05:42
【问题描述】:
我正在尝试使用 OpenMP 中的任务实现并行算法。 并行编程模式是基于生产者-消费者的思想,但是 由于消费者进程比生产者慢,我想使用一些 生产者和几个消费者。 主要思想是创建与生产者一样多的操作系统线程,然后每个 这些将创建要并行完成的任务(由消费者)。每一个 生产者将与一定数量的消费者相关联(即 numCheckers/numSeekers)。 我在英特尔双芯片服务器上运行算法,每个芯片有 6 个内核。 问题是当我只使用一个生产者(搜索者)并且数量越来越多时 消费者(跳棋)的性能下降得非常快,因为数量 消费者增长(见下表),即使正确的核心数量是 以 100% 的速度工作。 另一方面,如果我增加生产者的数量,平均时间 减少或至少保持稳定,即使有成比例的数量 消费者。 在我看来,所有的改进都是通过输入的划分来实现的 在生产者之间,任务只是窃听。但同样,我没有任何 解释一个生产者的行为。我是否遗漏了什么 OpenMP 任务逻辑?我是不是做错了什么?
-------------------------------------------------------------------------
| producers | consumers | time |
-------------------------------------------------------------------------
| 1 | 1 | 0.642935 |
| 1 | 2 | 3.004023 |
| 1 | 3 | 5.332524 |
| 1 | 4 | 7.222009 |
| 1 | 5 | 9.472093 |
| 1 | 6 | 10.372389 |
| 1 | 7 | 12.671839 |
| 1 | 8 | 14.631013 |
| 1 | 9 | 14.500603 |
| 1 | 10 | 18.034931 |
| 1 | 11 | 17.835978 |
-------------------------------------------------------------------------
| 2 | 2 | 0.357881 |
| 2 | 4 | 0.361383 |
| 2 | 6 | 0.362556 |
| 2 | 8 | 0.359722 |
| 2 | 10 | 0.358816 |
-------------------------------------------------------------------------
我的代码的主要部分是休闲:
int main( int argc, char** argv) {
// ... process the input (read from file, etc...)
const char *buffer_start[numSeekers];
int buffer_len[numSeekers];
//populate these arrays dividing the input
//I need to do this because I need to overlap the buffers for
//correctness, so I simple parallel-for it's not enough
//Here is where I create the producers
int num = 0;
#pragma omp parallel for num_threads(numSeekers) reduction(+:num)
for (int i = 0; i < numSeekers; i++) {
num += seek(buffer_start[i], buffer_len[i]);
}
return (int*)num;
}
int seek(const char* buffer, int n){
int num = 0;
//asign the same number of consumers for each producer
#pragma omp parallel num_threads(numCheckers/numSeekers) shared(num)
{
//only one time for every producer
#pragma omp single
{
for(int pos = 0; pos < n; pos += STEP){
if (condition(buffer[pos])){
#pragma omp task shared(num)
{
//check() is a sequential function
num += check(buffer[pos]);
}
}
}
#pragma omp taskwait
}
return num;
}
【问题讨论】:
-
您启用了嵌套并行,不是吗?请注意,标准规定任务执行可能会延迟到达到调度点(例如
taskwait)。任务中还有num的数据竞争。您应该使用atomic构造来保护累积。如果您的系统由两个 AMD64 芯片或 Nehalem 和后 Nehlaem Intel 芯片组成,请记住 NUMA 位置。
标签: c multithreading task openmp