在fortran代码的gprof输出上_IO_wfile是什么?

时间:2012-04-10 12:09:04

标签: fortran intel-fortran gprof

我有一些使用intel fortran编译器ifort编译的fortran代码。当我使用gprof进行配置文件测试时,我得到的大部分时间用于IO操作,我想找到文件的结尾,但我找不到更多关于此的文档:

index % time    self  children    called     name
                                                 <spontaneous>
[1]     20.6    0.07    0.00                 _IO_wfile_seekoff [1]
-----------------------------------------------
                                                 <spontaneous>
[2]     20.6    0.07    0.00                 sforcepf_ [2]
-----------------------------------------------
                                                 <spontaneous>
[3]     20.6    0.02    0.05                 _IO_wfile_underflow [3]
                0.01    0.04  258716/258717      strncmp [4]
-----------------------------------------------
                0.00    0.00       1/258717      _IO_wdefault_doallocate [15]
                0.01    0.04  258716/258717      _IO_wfile_underflow [3]
[4]     14.7    0.01    0.04  258717         strncmp [4]
                0.04    0.00 3104592/3109256     strerror_r [5]
-----------------------------------------------
                0.00    0.00    4664/3109256     __strcmp_sse42 [14]
                0.04    0.00 3104592/3109256     strncmp [4]
[5]     11.8    0.04    0.00 3109256         strerror_r [5]
-----------------------------------------------

所以,问题是,这个IO是针对Linux,还是针对ifort,还是针对fortran?我正在尝试优化此代码,并且在google中找不到有关此术语的有用信息。

3 个答案:

答案 0 :(得分:9)

您编写Fortran语句。英特尔Fortran编译器将这些语句转换为汇编程序,包括对系统函数的调用。例如,strncmp是ISO C标准函数,用于比较字符串的各个部分。因此,看起来您正在编写Fortran语句来比较字符串,而英特尔Fortran编译器正在调用现有函数来实现比较。其中一些系统功能本身将通过调用平台上提供的更基本功能来实现(部分)。

gprof向您显示对编译产品中引用的函数的调用。您看到的大部分内容都特定于Linux I / O - 在Windows机器上,I / O将使用具有不同名称的类似功能。您看到的一些内容可能是英特尔编译器特有的,所有英特尔编译器都使用相同的(英特尔创建的)功能进行某些操作,并且该功能使用特定于平台的低级功能。

除非你准备重写这些低级函数,并冒着使用相同函数将其搞砸到其他程序的风险,否则你可以做的唯一优化就是不经常调用它们。例如,如果您有理由认为读取文件末尾是一项昂贵的I / O操作,并且您的程序策略是读取文件,直到您阅读结束然后处理出现的错误,那么你可能想要实施一个优秀的计划战略。这比重写低级I / O例程更容易,后者处理策略的后果。

答案 1 :(得分:3)

假设您使用任何语言编写以下内容

loop for a long time
  write something to somewhere

并使用 gprof 对其进行分析。

gprof 在IO或任何其他阻塞状态期间暂停采样。 这个程序执行的时间非常短,但是它所花费的周期很多,其中大部分用于进入和退出启动IO并等待它完成的内置库例程。

因此,如果您的计划是这样的,那么您所看到的内容就不足为奇了。

There's a lot more to this issue.

答案 2 :(得分:3)

看起来您正在看Fortran I / O操作。 ifort格式化的I / O非常慢。如果使用标准输入/标准输出重定向,则会更糟;管道更糟糕 - 英特尔专家警告不要这样做。 gfortran并不是那么糟糕,但仍然很慢。

一些可能性是:

  • 尝试尽可能少的I / O调用(例如,将它们移出循环)
  • 直接避免重定向和读/写文件
  • blocksize
  • 中查看buffercountopen()和其他与I / O相关的选项

如果这还不够,I / O是您的主要瓶颈,您可以考虑:

  • ifort中查看流I / O,它更快,你可以做一些事情,比如自己缓冲,以避免多次通话。但是,它可能引入可移植性问题,因为其他编译器可能还不支持它或者以不同方式执行它。不要在标准输入/输出上执行(可能在ifort中工作,但它没有记录,并且不能与其他编译器一起使用)。
  • 使用iso_c_binding调用C函数 - 例如如果您要写入标准输出,可以从libc调用puts()。这是更快,实际上非常便携,因为它是标准的,事实上,我所做的每个操作系统上的每个编译器(Win32 / linux64 / sparc solaris)都需要(并自动链接)libc;但它相当丑陋,你必须自己处理诸如null终止之类的事情(例如通过编写包装器函数),这会掩盖代码并导致错误。
  • 不要将这些方法中的任何一种与常规I / O混合在一起!

如果您在代码中明确进行字符串比较,这些最终也会调用strncmp()。 ifort中的字符串操作也有点慢(虽然远不如I / O那么糟),所以如果你正在做 A LOT 的比较,你可能会通过调用{{1}来获得几秒钟直接,但我建议反对 - 增益不是那么大,再次,它掩盖了代码。