Linux下FORTRAN77程序的Profile工具

来源:互联网 发布:淘宝衣服尺寸图多大 编辑:程序博客网 时间:2024/05/19 17:59

参照前面转载的文章,完成了Linux下FORTRAN77程序的Profile,主要是查看函数调用关系

gprof的基本用法:

1. 使用 -pg 选项编译和链接你的应用程序

    在gcc编译程序的时候,加上-pg选项,例如:

    gcc -pg -o test test.c

    这样就生成了可执行文件test。如果是大项目,就在makefile里面修改编译选项,-pg放在那里都行。

2. 执行你的应用程序使之生成供gprof 分析的数据

    运行刚才的程序:./test,这样就生成了一个gmon.out文件,该文件就包含了profiling的数据。

3. 使用gprof 分析你的应用程序生成的数据

    gprof test gmon.out > profile.txt

 

使用注意:
1)一般gprof只能查看用户函数信息。如果想查看库函数的信息,需要在编译是再加入“-lc_p”编译参数代替“-lc”编译参数,这样程序会链接libc_p.a库,才可以产生库函数的profiling信息。
2) gprof只能在程序正常结束退出之后才能生成程序测评报告,原因是gprof通过在atexit()里注册了一个函数来产生结果信息,任何非正常退出都不会执行atexit()的动作,所以不会产生gmon.out文件。如果你的程序是一个不会退出的服务程序,那就只有修改代码来达到目的。如果不想改变程序的运行方式,可以添加一个信号处理函数解决问题(这样对代码修改最少),例如:
static void sighandler( int sig_no )   
{   
      exit(0);   
}   
signal( SIGUSR1, sighandler );
当使用kill -USR1 pid 后,程序退出,生成gmon.out文件。
 
 
接下来重点进行第二种情况的分析,既如何分析一个不会退出的程序,具体实例:

编辑test.c

 

#include "stdio.h"

#include "stdlib.h"

#include <signal.h>

void a(){

   printf("/t/t+---call a() function\n");

}

void c(){

   printf("/t/t+---call c() function\n");

}

int b() {

   printf("/t+--- call b() function\n");

   a();

   c();

   return 0;

}

 

static void sighandler( int sig_no )

{

     exit(0);

}

 

int main(){

   printf(" main() function()\n");

   b();

   while(1)

       {

          printf("while loop");

          signal(SIGUSR1,sighandler);

       }

}

 

  上面的test.c是一个死循环的程序,如何利用gprof分析函数调用关系,可以通过加入信号处理函数来解决,既(signal(SIGUSR1,sighandler);)。

  具体步骤:

1.       gcc -pg -o test test.c

2.      运行./test,此时一直处于循环状态,不会生成gmon.out文件。

3.      另外开启一个终端,运行ps –aux命令,查看test进程,运行kill pid命令切断test进程。

4.      此时在程序执行目录下生成gmon.out文件,可以分析程序执行性能和函数调用关系了。

 

 

 

 

 

上面都是针对c语言的方法,下面针对FORTRAN77给出具体的实现方法

 

首先给出简单的signal函数用法:tes.t_signal.f

PROGRAM MAIN

      EXTERNAL h_abort

      INTEGER iret1, iret2, procnum

      iret1 = SIGNAL(SIGABRT, h_abort, -1)

      WRITE(*,*) 'Set signal handler. Return =', iret1

 

      iret2 = KILL(procnum, SIGABRT)

      WRITE(*,*) 'Raised signal. Return = ',iret2

      END

 

      INTEGER FUNCTION h_abort (sig_num)

      INTEGER sig_num

 

      WRITE(*,*) 'In signal handler forSIG$ABORT'

      WRITE(*,*) 'signum = ', sig_num

      h_abort = 1

          END

 

下面给出简单MPI的helloworld函数 helloworld.f函数

program main

      implicit none

      include 'mpif.h'

 

      integer n, myid, numprocs, i, j,rc

      integer begin_col,end_col,ierr

      integer status(MPI_STATUS_SIZE)

      call MPI_INIT( ierr )

      call MPI_COMM_RANK( MPI_COMM_WORLD, myid,ierr )

      call MPI_COMM_SIZE( MPI_COMM_WORLD,numprocs, ierr )

      write(*,10)myid,numprocs

   10 format('Hello World! Process',I2,' of',I1,' is alive')

      call MPI_Finalize(rc)

          end

 

下面是加入了信号处理函数的test_while.f

program main

      include 'mpif.h'

 

      EXTERNAL h_abort

      INTEGER iret1, iret2, procnum

 

      integer n, myid, numprocs, i, j,rc

      integer begin_col,end_col,ierr

      integer status(MPI_STATUS_SIZE)

      call MPI_INIT( ierr )

      call MPI_COMM_RANK( MPI_COMM_WORLD, myid,ierr )

      call MPI_COMM_SIZE( MPI_COMM_WORLD, numprocs,ierr )

 

      i=1

      do while(i .LT. 100)

      write(*,10)myid,numprocs

   10 format('Hello World! Process',I2,' of',I1,' is alive')

 

      iret1 = SIGNAL(SIGABRT, h_abort, -1)

      iret2 = KILL(procnum, SIGABRT)

 

      end do

      call MPI_Finalize(rc)

      end

 

      INTEGER FUNCTION h_abort (sig_num)

      INTEGER sig_num

      h_abort = 1

          END

 

从而可以应用profile分析函数性能和函数调用关系。

1. 使用 -pg 编译和链接你的应用程序。
2. 执行你的应用程序使之生成供gprof 分析的数据。
3. 使用gprof 程序分析你的应用程序生成的数据。

 

<注意> 有些编译器可能会出现编译错误,只需要换个编译器就可以解决,具体原因不是很清楚。我用的编译器是Mvapich2-1.8_Intel。

如下面的错误:

test.f:26.16:

 

     status = signal(signum,kill,flag)                               

               1

Error: Too many arguments in call to 'signal' at(1)      

报错:有多余的参数.

 

 

参考资料:http://www.slac.stanford.edu/comp/unix/package/intel_tools/ifort/mergedProjects/lref_for/source_files/rfsignl.htm