没有使用OpenMP的无用printf加速

时间:2010-04-26 06:27:26

标签: multithreading printf parallel-processing openmp performance

我刚刚编写了第一个OpenMP程序,该程序并行化了一个简单的for循环。我在双核机器上运行代码,从1个线程到2个线程时看到了一些加速。但是,我在学校的Linux服务器上运行相同的代码,并没有看到加速。在尝试了不同的事情后,我终于意识到删除一些无用的printf语句会导致代码显着加速。下面是我并行化的代码的主要部分:

#pragma omp parallel for private(i)
for(i = 2; i <= n; i++)
{
  printf("useless statement");
  prime[i-2] = is_prime(i);
}

我想printf的实现有很大的开销,OpenMP必须与每个线程重复。导致这种开销的原因以及为什么OpenMP无法克服它?

4 个答案:

答案 0 :(得分:6)

猜测,但也许stdout被锁定了?

通常,printf是一项昂贵的操作,因为它与其他资源(例如文件,控制台等)交互。

我的实验经验是,Windows控制台上的printf非常慢,在Linux控制台上相对快得多,但如果重定向到文件或/ dev / null则速度最快。

我发现printf-debugging会严重影响我的应用程序的性能,我会谨慎使用它。

尝试将应用程序重定向到文件或/ dev / null,看看是否有任何明显的影响;这将有助于缩小问题所在的范围。

当然,如果printfs没用,为什么它们在循环中呢?

答案 1 :(得分:3)

要扩展@Will的答案......

我不知道stdout是否受到锁定的保护,但我很确定写入它是在软件堆栈中的某个时刻序列化的。包含printf语句OP可能是对stdout执行大量串行写操作的时间,而不是循环的并行执行。

我建议OP修改printf语句以包含i,看看会发生什么。

至于双核机器的明显加速 - 是否具有统计意义?

答案 2 :(得分:1)

这里有一个并行for循环,但调度未指定。

#pragma omp parallel for private(i)
for(i = 2; i <= n; i++)

OpenMP 3.0标准中定义了一些调度类型。可以通过将OMP_SCHEDULE环境变量设置为type[,chunk]其中

来更改它们
  • 类型静态动态指导自动之一
  • chunk 是一个可选的正整数,用于指定块大小

更改计划类型的另一种方法是调用openmp函数omp_set_schedule

is_prime功能可以相当快。 /我建议/

  prime[i-2] = is_prime(i);

因此,问题可能来自错误的调度模式,当在调度屏障之前执行少量数字时。

printf里面有2个部分/我认为glibc是流行的Linux libc实现/

  1. 解析格式字符串并将所有参数放入缓冲区
  2. 将缓冲区写入文件描述符(到FILE缓冲区,因为stdout默认由glibc缓冲)
  3. printf的第一部分可以并行完成,但第二部分是一个关键部分,它被_IO_flockfile锁定。

答案 3 :(得分:0)

你的时间是什么 - printf的速度要慢得多吗?在一些紧凑的循环中,printf可能占用总计算时间的很大一部分;例如,如果is_prime()非常快,那么性能更多地取决于对printf的调用次数,而不是对is_prime()的(并行)调用次数。