Multithreading 使用无用的printf';s使用OpenMP

Multithreading 使用无用的printf';s使用OpenMP,multithreading,printf,parallel-processing,openmp,performance,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 st

我刚刚编写了我的第一个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);
}
#专用pragma omp并行(i)

对于(i=2;i推测,但可能标准装置由锁保护

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

我的经验是,printf在Windows控制台上速度非常慢,在Linux控制台上速度相当快,但如果重定向到文件或/dev/null,速度仍然最快

我发现printf调试会严重影响我的应用程序的性能,而且我很少使用它

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


当然,如果printfs是无用的,为什么它们会出现在循环中呢?

要扩展一下@Will的答案

我不知道stdout是否由锁保护,但我很确定对它的写入是在软件堆栈中的某个点进行序列化的。使用
printf
语句,OP可能是对大量串行写入stdout的执行进行计时,而不是对循环的并行执行

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


至于双核机器上的明显加速——在统计上有显著性吗?

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

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

#pragma omp parallel for private(i)
for(i = 2; i <= n; i++)
因此,问题可能来自错误的调度模式,即在调度之前执行少量任务

和<代码> PRINTF 里面有2个部分:我认为GLUBC是流行的Linux LIBC实现/< /P>

  • 解析格式字符串并将所有参数放入缓冲区
  • 将缓冲区写入文件描述符(写入文件缓冲区,因为默认情况下标准输出由glibc缓冲)

  • printf的第一部分可以并行完成,但第二部分是一个关键部分,它被
    \u IO\u flockfile
    锁定;听过Prime Sieve吗?你使用什么编译器?什么版本?printf是为了调试。是的,glibc用锁来保护stdout,因为它会缓冲它。明显的速度-up并没有以统计上很强的方式显示出来。我只是再次运行它,用1个线程运行了9秒,用2个线程运行了7秒。但当我在学校的服务器上运行它时,根本没有明显的加速(直到我去掉printf语句).我想我现在的主要问题只是好奇:printf的幕后发生了什么,它会阻碍OMP并行化for循环?我想这就像你说的:它最终必须序列化…+1;printf()是对的这是一个非常昂贵的操作,但这实际上有助于加快速度,其他方面都保持不变;独立的昂贵任务并行性良好。关键问题是它们是否真的独立。正如马克所说,它们正在访问共享资源(stdout)因此,在某种程度上,最终必须对内容进行序列化,而序列化必然会降低并行性能。
      prime[i-2] = is_prime(i);