xml call tree

To be sure, there are many great profilers out there; each with different learning curves and costs ranging from free to a kidney. If you face a new distribution or one you would like to develop with, there is no substitute for rolling your own; follow this bash script, rebuild and filter the output and you have an xml call tree with times for calls, and pointers to source code and line number. This is applied to the fortran code(s) in quantum espresso, you can readily adapt to your own needs. Caveat: There are a variety of filter steps in the pipeline; taking into account fortran syntax and different programming styles is difficult ūüôā Once you have your stdout filtered to proper xml, you can view in something like eclipse eg,. attached image. Be aware also that you can and will write very large files; I exclude many i/o and related functions, these you can poke with strace or similar anyway.


 #!/bin/bash

#set source and destination paths
PROFILE_DIR_PATH=~/scratch/espresso-PRACE/PW
PROFILE_BAK_PATH=~/scratch/PW_BAK

#set include/exclude strings; these i/o related function calls won't be timed later
EXCLUDE="!(\$0~\"bcast\")&&!(\$0~\"info\")&&!(\$0~\"clock\")&&!(\$0~\"report\")&&!(\$0~\"mp\")&&!(\$0~\"!\")&&!(\$0~\"error\")&&\
!(\$0~\"read\")&&!(\$0~\"write\")&&!(\$0~\"plot\")&&!(\$0~\"delete\")&&!(\$0~\"scan\")&&!(\$0~\"specific\")&&!(\$0~\"print\")&&!(\$0~\"format\")"
INCLUDE="(\$0~\"bcast\")||(\$0~\"info\")||(\$0~\"clock\")||(\$0~\"report\")||(\$0~\"mp\")||(\$0~\"!\")||(\$0~\"error\")||\
(\$0~\"read\")||(\$0~\"write\")||(\$0~\"plot\")||(\$0~\"delete\")||(\$0~\"scan\")||(\$0~\"specific\")||(\$0~\"print\")||(\$0~\"format\")"


#do once
#mkdir  -p $PROF_BAK_PATH
#cp -iu $PROF_DIR_PATH/* $PROF_BAK_PATH

declare -a file_list

#filenames to array
file_list=$(ls -l ${PROFILE_BAK_PATH} | gawk '/f90/ {print $9}')

cnt=1000;

#parse files & pretty up, inserting write statements and timers
for x in $file_list
do
    let "cnt+=1"
    sed 's/\,\&/\,\ \&/g' $PROFILE_BAK_PATH/$x | \
    sed 's/)/)\ /g' | \
    gawk 'BEGIN{IGNORECASE=1; FS="&"} (NF<=1) || ($0~"#") || !($1~"if") || ($0~"!") || '$INCLUDE' {print $0}; \
    (NF>1) && !($0~"#") && ($1~"if") && !($0~"!") && '$EXCLUDE' {printf("%s ",$1)}' |\
    gawk 'BEGIN{IGNORECASE=1;} /if/ { if (($0~"&") && !($0~"!") &&!($0~"#") \
    && !($NF~"&") && !($0~"error")) {gsub(/&/," ");print} else print $0}; \
    !/if/ {print $0}' |\
    gawk 'BEGIN{IGNORECASE=1; } (($1~"if")||($1~"else")) && (length($0)>100) \
    {{for (i=1;i<=NF;i++) printf("%s",$i);} printf("\n")} !(($1~"if")||($1~"else")) || (length($0)<=100) {print $0}' |\
    gawk 'BEGIN{IGNORECASE=1; FS="&"} (NF==1) || ($0~"#") || !($0~"call") || '$INCLUDE' {print $0}; \
    (NF>1) && !($0~"#") && ($0 ~ "call") && '$EXCLUDE' {printf("%s ",$1)}' |\
    gawk 'BEGIN{IGNORECASE=1; FS="&"} (NF==1) || ($0~"#") || !($0~"call") || '$INCLUDE' {print $0}; \
    (NF>1) && !($0~"#") && ($0 ~ "call") && '$EXCLUDE' {printf("%s ",$1)}' |\
    gawk 'BEGIN{IGNORECASE=1;} !/call/{print $0}; /call/ {for (i=1; i<=NF; i++) printf("%s",$i); printf("\n")}' | \
    sed 's/call/\ call\ /g' | \
    sed 's/CALL/\ call\ /g' |\
    sed 's/(/\ (/g' | \
    gawk 'BEGIN{IGNORECASE=1; ch=1;} !/call/ || '$INCLUDE' {print $0}; \
    /call/ && '$EXCLUDE' {pos=pos+1; print " call date_and_time(values=time_array_0) "; \
    for (i=1; i<=NF; i++) {if ($i=="call") ch=i+1;} ;\
    print " start_time = time_array_0(6)*60 + time_array_0(7) + 0.001*time_array_0(8) "; \
    print " write(*,*)\" <",$ch,">\" "; print $0; \
    print " call date_and_time(values=time_array_1) "; \
    print " finish_time=time_array_1(6)*60 + time_array_1(7) + 0.001*time_array_1(8) "; \
    print " write(*,*)\" <meta> \",1000*(finish_time-start_time),\" : ",NR," : ",'$cnt'," : ",$ch," </meta>\" " ;\
    print " write(*,*)\" <source> ~/espresso-PRACE/PW/'$x' </source> \" " ;  \
    print " write(*,*)\"</",$ch,">\" " ; }' | \
    gawk 'BEGIN{IGNORECASE=1; } {print $0;} /IMPLICIT NONE/{ print "INTEGER :: time_array_0(8), time_array_1(8)"; \
    print "REAL :: start_time, finish_time"; }' |\
    gawk 'BEGIN{FS=","} ($0~"call" && (NF <=5)) || ($0 ~ "!") || !/call/{print $0} \
    $0~"call" && (NF>5) && !($0 ~ "!") {print $1,",",$2,",",$3,",",$4,",&"; for (i=5;i<NF;i++) \
    printf("%s,",$i); printf("%s \n",$NF)}' > $PROFILE_DIR_PATH/$x
done

#copy in hard cases; don't bother
cp $PROFILE_BAK_PATH/input.f90 $PROFILE_DIR_PATH
cp $PROFILE_BAK_PATH/symme.f90 $PROFILE_DIR_PATH
cp $PROFILE_BAK_PATH/g_psi.f90 $PROFILE_DIR_PATH
cp $PROFILE_BAK_PATH/pw2blip.f90 $PROFILE_DIR_PATH
cp $PROFILE_BAK_PATH/stop_run.f90 $PROFILE_DIR_PATH
cp $PROFILE_BAK_PATH/vcsmd.f90 $PROFILE_DIR_PATH
cp $PROFILE_BAK_PATH/dynamics_module.f90 $PROFILE_DIR_PATH
cp $PROFILE_BAK_PATH/paw_init.f90 $PROFILE_DIR_PATH
cp $PROFILE_BAK_PATH/compute_becsum.f90 $PROFILE_DIR_PATH
cp $PROFILE_BAK_PATH/h_epsi_her_*.f90 $PROFILE_DIR_PATH
cp $PROFILE_BAK_PATH/wannier_*.f90 $PROFILE_DIR_PATH
cp $PROFILE_BAK_PATH/wfcinit.f90 $PROFILE_DIR_PATH

exit

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s