Merge lp:~albertog/siesta/4.0-json-time into lp:siesta/4.0

Proposed by Alberto Garcia
Status: Merged
Merged at revision: 558
Proposed branch: lp:~albertog/siesta/4.0-json-time
Merge into: lp:siesta/4.0
Diff against target: 173 lines (+79/-12) (has conflicts)
4 files modified
Docs/siesta.tex (+6/-1)
Src/siesta_analysis.F (+4/-0)
Src/timer_tree.f90 (+63/-11)
version.info (+6/-0)
Text conflict in version.info
To merge this branch: bzr merge lp:~albertog/siesta/4.0-json-time
Reviewer Review Type Date Requested Status
Nick Papior Approve
Review via email: mp+337797@code.launchpad.net

Description of the change

When using the tree-timer, a 'time.json' file in JSON format is written.
This file can be used by third-party scripts to process timing data.

Also, add a new intermediate timing section for 'siesta_analysis'.

To post a comment you must log in.
Revision history for this message
Alberto Garcia (albertog) wrote :

I forgot to add that this has been prompted by the need to set up a benchmarking workflow in AiiDA. The Siesta plugin now processes the timing information in the time.json file.

Revision history for this message
Nick Papior (nickpapior) wrote :

I have made a merge request that tries to solve some of the things I have remarked below.

Note they are comments/remarks. I however think the logic is easier by not having two optional arguments.

Revision history for this message
Alberto Garcia (albertog) wrote :
Download full text (4.8 KiB)

Dear Nick,

Thank you for reviewing this.
My comments:

— I did not want to introduce another dependency for m_io. This write operation is very localized in time, so there is no need to reserve
a unit in the way of m_io.
- My json schema is not perfect: the “info nodes: time, calls, and %, are logically also children of the section objects, but conceptually different (they are “leaf info” instead of tree branches. So with a view to a future scripting capability of the json file, I put the “_” in front to clearly mark them as different. This is obviously not fool-proof.
- I agree that we do not need two different optional arguments.

Let me know if you agree, and I will just merge the interface simplification from your changes.

  Best regards,

  Alberto

> On 19 Feb 2018, at 09:21, Nick Papior <email address hidden> wrote:
>
> I have made a merge request that tries to solve some of the things I have remarked below.
>
> Note they are comments/remarks. I however think the logic is easier by not having two optional arguments.
>
> Diff comments:
>
>>
>> === modified file 'Src/timer_tree.f90'
>> --- Src/timer_tree.f90 2016-01-25 16:00:16 +0000
>> +++ Src/timer_tree.f90 2018-02-15 15:48:27 +0000
>> @@ -266,31 +269,71 @@
>> enddo
>> p%data%totTime = globaltime + 1.0e-6_dp
>>
>> + json_output = .true.
>> + call get_unit_number(js_lun)
>> + open(unit=js_lun,file="time.json",form="formatted", &
>> + action="write",position="rewind")
>> +
>> write(*,"(/,a20,T30,a6,a12,a8)") "Section","Calls","Walltime","%"
>> - call walk_tree(p,0)
>>
>> + write(js_lun,*) '{'
>> + call walk_tree(p,0,json=json_output,js_lun=js_lun)
>> + write(js_lun,*) '}'
>> + if (json_output) close(js_lun)
>> +
>> end subroutine timer_report_global
>>
>> !------------------------------------------------
>> - recursive subroutine walk_tree(p,level,maxlevel)
>> + recursive subroutine walk_tree(p,level,maxlevel,json,js_lun)
>> type(section_t), intent(in),target :: p
>> integer, intent(in) :: level
>> integer, intent(in), optional:: maxlevel
>> + logical, intent(in), optional:: json
>> + integer, intent(in), optional:: js_lun
>>
>> integer :: i
>> - character(len=40) fmtstr
>> + character(len=40) fmtstr, fmt_json, fmt_json_head
>> + logical :: json_output
>>
>> + json_output = .false.
>> + if (present(json)) then
>> + json_output = json
>> + if (.not. present(js_lun)) then
>> + call die("Need a js_lun for json timer output")
>> + endif
>> + endif
>> if (present(maxlevel)) then
>> if (level > maxlevel) RETURN
>> endif
>> pd => p%data
>> write(fmtstr,"(a,i0,a1,a)") "(", level+1, "x", ",a20,T30,i6,f12.3,f8.2)"
>> +
>> write(*,fmtstr) pd%name, pd%nCalls, &
>> pd%totTime, 100*pd%totTime/globaltime
>> + if (json_output) then
>> + write(fmt_json,"(a,i0,a1,a)") "(",2*level+1,"x",",a,i0,a,f12.3,a,f8.2)"
>> + write(fmt_json_head,"(a,i0,a)") "(", 2*level+1, "x,a)"
>> + write(js_lun,fmt=fmt_json,advance="no") &
>> + '"' // trim(pd%name) // '": { "_calls": ', pd%nCalls, &
>> ...

Read more...

Revision history for this message
Nick Papior (nickpapior) wrote :

Dear Alberto,

m_io: no worries. I wouldn't mind having that dependency, but your call.
tree vs branch: I see, perhaps we could mark them with "leaf_calls" which clarifies this?

Agreed! ;)

review: Approve
lp:~albertog/siesta/4.0-json-time updated
559. By Alberto Garcia

Use only the presence of json unit as signal to dump JSON

(Thanks to Nick Papior)

We keep the get_unit_number internal routine for now, to avoid
an extra dependency on m_io.

Revision history for this message
Nick Papior (nickpapior) wrote :

@Alberto, should I merge in this branch, or will you?

Revision history for this message
Alberto Garcia (albertog) wrote :

I will merge it shortly.

----- El 20 de Feb 2018, a las 21:15, Nick Rubner Papior <email address hidden> escribió:

| @Alberto, should I merge in this branch, or will you?
| --
| https://code.launchpad.net/~albertog/siesta/4.0-json-time/+merge/337797
| You are the owner of lp:~albertog/siesta/4.0-json-time.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'Docs/siesta.tex'
2--- Docs/siesta.tex 2017-12-28 13:00:52 +0000
3+++ Docs/siesta.tex 2018-02-19 13:31:01 +0000
4@@ -6595,7 +6595,12 @@
5 \index{UseTreeTimer@{\bf UseTreeTimer}}
6
7 Enable an experimental timer which is based on wall time on the master
8-node and is aware of the tree-structure of the timed sections.
9+node and is aware of the tree-structure of the timed sections. At the
10+end of the program, a report is generated in the output file, and a
11+{\tt time.json} file in JSON format is also
12+written. \index{JSON timing report@{\bf JSON timing report}}
13+This file can be
14+used by third-party scripts to process timing data.
15
16 {\it Default value:} {\tt .false.}
17
18
19=== modified file 'Src/siesta_analysis.F'
20--- Src/siesta_analysis.F 2017-10-04 09:48:27 +0000
21+++ Src/siesta_analysis.F 2018-02-19 13:31:01 +0000
22@@ -94,6 +94,8 @@
23 endif
24 endif
25
26+ call timer( 'siesta_analysis', 1 )
27+
28 ! All the comments below assume that this compatibility option
29 ! is not used.
30 ! Note also that full compatibility cannot be guaranteed
31@@ -456,6 +458,8 @@
32 ! -- Set xa to xa_last at the top of this file. Write any "next iter" coordinate file
33 ! in 'siesta_move'
34
35+ call timer( 'siesta_analysis', 2 )
36+
37 !--------------------------------------------------------------------------- END
38 END subroutine siesta_analysis
39 END module m_siesta_analysis
40
41=== modified file 'Src/timer_tree.f90'
42--- Src/timer_tree.f90 2016-01-25 16:00:16 +0000
43+++ Src/timer_tree.f90 2018-02-19 13:31:01 +0000
44@@ -218,9 +218,10 @@
45 end subroutine timer_all_off
46
47 !------------------------------------------------
48- subroutine timer_report(secname)
49+ subroutine timer_report(secname,file_unit)
50 character(len=*), optional :: secname
51-
52+ integer, intent(in), optional :: file_unit
53+
54 integer :: i, loc
55 logical :: full
56
57@@ -253,7 +254,7 @@
58 !------------------------------------------------
59 subroutine timer_report_global()
60
61- integer :: i
62+ integer :: i, js_lun
63 type(times_t), pointer :: qd
64
65 p => global_section
66@@ -266,31 +267,68 @@
67 enddo
68 p%data%totTime = globaltime + 1.0e-6_dp
69
70+ ! Open JSON
71+ call get_unit_number(js_lun)
72+ open(unit=js_lun, file="time.json", form="formatted", &
73+ action="write",position="rewind")
74+
75 write(*,"(/,a20,T30,a6,a12,a8)") "Section","Calls","Walltime","%"
76- call walk_tree(p,0)
77-
78+ ! Due to border logic we need this top-level wrapping
79+ write(js_lun,"(a)") "{"
80+ call walk_tree(p,0, js_lun=js_lun)
81+ write(js_lun,"(a)") "}"
82+
83+ close(js_lun)
84+
85 end subroutine timer_report_global
86
87 !------------------------------------------------
88- recursive subroutine walk_tree(p,level,maxlevel)
89+ recursive subroutine walk_tree(p,level,maxlevel,js_lun)
90 type(section_t), intent(in),target :: p
91 integer, intent(in) :: level
92 integer, intent(in), optional:: maxlevel
93+ integer, intent(in), optional:: js_lun
94
95 integer :: i
96- character(len=40) fmtstr
97+ character(len=64) fmtstr, fmt_json, fmt_json_head
98+ logical :: json_output
99
100+ ! Determine whether we should output JSON
101+ ! If the unit is there, we output to JSON as well
102+ json_output = present(js_lun)
103+
104 if (present(maxlevel)) then
105 if (level > maxlevel) RETURN
106- endif
107+ end if
108+
109 pd => p%data
110 write(fmtstr,"(a,i0,a1,a)") "(", level+1, "x", ",a20,T30,i6,f12.3,f8.2)"
111- write(*,fmtstr) pd%name, pd%nCalls, &
112- pd%totTime, 100*pd%totTime/globaltime
113+
114+ write(*,fmtstr) pd%name, pd%nCalls, pd%totTime, 100*pd%totTime/globaltime
115+ if (json_output) then
116+ write(fmt_json,"(a,i0,a1,a)") "(",2*level+1,"x",",a,i0,a,f12.3,a,f8.2)"
117+ write(fmt_json_head,"(a,i0,a)") "(", 2*level+1, "x,a)"
118+ write(js_lun,fmt=fmt_json,advance="no") &
119+ '"' // trim(pd%name) // '": { "_calls": ', pd%nCalls, &
120+ ', "_time": ', pd%totTime, &
121+ ', "_%": ', 100*pd%totTime/globaltime
122+ end if
123 if (p%nchildren /= 0) then
124+ if (json_output) write(js_lun,"(a)") ","
125 do i=1,p%nchildren
126- call walk_tree(p%child(i),level+1,maxlevel)
127+ call walk_tree(p%child(i),level+1,maxlevel, js_lun)
128+ if (json_output) then
129+ if (i < p%nchildren) then
130+ write(js_lun,fmt="(a)") ','
131+ else
132+ write(js_lun,*) ! just new line
133+ endif
134+ endif
135 enddo
136+ ! End the parent section with an indented '}'
137+ if (json_output) write(js_lun,fmt=fmt_json_head,advance="no") "}"
138+ else
139+ if (json_output) write(js_lun,fmt="(a)",advance="no") "}"
140 endif
141
142 end subroutine walk_tree
143@@ -353,4 +391,18 @@
144 endif
145 end subroutine current_time
146
147+subroutine get_unit_number(lun)
148+integer, intent(out) :: lun
149+
150+logical :: used
151+integer :: iostat
152+
153+do lun= 10, 99
154+ inquire(unit=lun, opened=used, iostat=iostat)
155+ if (iostat .ne. 0) used = .true.
156+ if (.not. used) return
157+enddo
158+call die("Cannot get unit for timer output")
159+end subroutine get_unit_number
160+
161 end module m_timer_tree
162
163=== modified file 'version.info'
164--- version.info 2018-02-19 08:15:36 +0000
165+++ version.info 2018-02-19 13:31:01 +0000
166@@ -1,1 +1,7 @@
167+<<<<<<< TREE
168 siesta-4.0--557
169+=======
170+siesta-4.0--555--json-time-4
171+
172+
173+>>>>>>> MERGE-SOURCE

Subscribers

People subscribed via source and target branches