Efficient Coding Practices Efficient Coding Practices OR How I Stopped Worrying and Learned to Love ing Things! Joshua D. Bodyfelt Max­Planck­Institute für Physik komplexer Systeme Condensed Matter Division MPI­PKS Research Group Informal Seminar ­ 05.02.2010 Online at: http://www.mpipks­dresden.mpg.de/~bodyfelt/Tutorials/Scripting.pdf A Bit of Motivation... A Bit of Motivation... “Josh, you must stop working hard, and start working efficient....” ­ Moritz Hiller, after +72 hours without sleep A Brief Synopsis A Brief Synopsis The Clydesdale – A Sample ForTran Code ● The Tack – General BASH (Bourne Again Shell) Syntax ● The Feedbag – I/O Redirection in BASH ● The Plow – Advanced I/O in BASH: HERE Blocks ● The Hitch­Tongue – S.G.E. Job Task Arrays ● The Sowed Field – HERE & gracebat scripting ● The Clydesdale – Sample Fortran Code The Clydesdale – Sample Fortran Code The Clydesdale – Sample Fortran Code The Clydesdale – Sample Fortran Code Equivalent to: cin >> A >> w >> d >> N; (C++) def main(A,w,d,N): (Python) The Tack – General BASH Syntax The Tack – General BASH Syntax ➢ Common Shell Commands http://tldp.org/LDP/abs/html/ Informative: date hostname logname echo top ps File­Based: basename cat cp mv rm cut chmod tar zip Path­Based: ls pwd dirname cd (­r option on many of the above) Operational: kill bc python FORTRAN BINARIES!!! Variables/Arrays: Assignment & Referencing ➢ Assigned by: scalar=value array=( value1 value2 … ) “....” → Substitution Quotes '.....' → Literal Quotes Referenced as: $ → “Substitution” {} → Gen. (Array) Substitution # → Array Length [ ] → Array Index (Zero'ed) @ → Complete Array * → “Wild Card” (dummy) $( ) → Command Substitution Simple Examples user@host> u=Koshchey; v=the; w=Deathless user@host> r="$u $v $w"; s='$u $v $w' user@host> echo $r; echo $s Koshchey the Deathless $u $v $w user@host> t=$u $v $w bash: the: command not found user@host> x=(Baba Yaga\'s Chicken Leg Hut) user@host> echo ${x}; echo ${x[@]}; echo ${#x[@]} Baba Baba Yaga's Chicken Leg Hut 5 user@host> echo ${x[1]} Yaga's user@host> ls test test.f90 test_perm.f90 user@host> b=($(ls ­1)) user@host> echo ${b[1]} test.f90 The Tack – General BASH Syntax, continued The Tack – General BASH Syntax, continued ➢ Variables/Arrays: Operations http://www.gnu.org/software/bc/manual/bc.html String Operations: ${variable:position:characters} → Trim # of characters from the given position ${variable%pattern} → Trim the shortest match from the end ${variable%%pattern} → Trim the longest match from the end ${variable##pattern} → Trim the longest match from the beginning ${variable#pattern} → Trim the shortest match from the beginning Mathematical Operations: $(( +­* )) → Simple Integer Arithmetic echo “scale=... commands” | bc <­l> → Real Arithmetic Simple Examples String Operations user@host> string="This is a test. It is only a test." user@host> echo ${string:5:8} is a tes user@host> echo ${string%test*} This is a test. It is only a user@host> echo ${string%%test*} This is a user@host> echo ${string#*test} . It is only a test. user@host> echo ${string##*test} . Note the importance (AND POSITION) of the Wild Card!! user@host> echo ${string##test*} This is a test. It is only a test. user@host> echo ${string%%test} This is a test. It is only a test. Mathematical Operations user@host> a=1 user@host> b=$((a+10)); c=$((b*5)) user@host> echo $b $c 11 55 user@host> pi=$(echo "scale=9; 22/7" | bc); echo $pi 3.142857142 user@host> pi=$(echo "scale=2; 22/7" | bc); echo $pi 3.14 ­l option imports a mathematics library user@host> pi=$(echo "scale=10; 4*a(1)" | bc ­l); echo $pi 3.1415926532 The “|” character is a pipe . It takes the stdout stdout from one from one The “|” character is a pipe. It takes the command and pipes it as stdin stdin to the second command. to the second command. command and pipes it as The Tack – General BASH Syntax, continued The Tack – General BASH Syntax, continued ➢ Flow Control If ­ Then: If [[ condition ]]; then ...<command list> fi Do ­ While: while [[ condition ]]; do ...<command list> done Simple Examples user@host> if [[ $animal == 'Dog' ]]; then echo $animal" is man's best friend."; fi user@host> if [[ $((1+1)) ­gt 2 ]]; then echo "Because the Party says so."; fi user@host> ResistCode=(Black Brown Red Orange Yellow Green Blue Violet Grey White); band=0 user@host> while [[ $band ­le $((${#ResistCode[@]}­1)) ]]; do > echo ${ResistCode[$band]} > band=$((band+1)) > done Reading Parameter Files: user@host> cat parameter.list | while read line; do echo $line; done ##### A, w, d, N ####### 0.0 1.0 0.0 1000 1.0 1.0 0.0 1000 2.0 1.0 0.0 1000 3.0 1.0 0.0 1000 This barely scratches the surface, but is deep enough to start scripting. For more, check out: http://tldp.org/LDP/abs/html/ The Feedbag – I/O Redirection in BASH The Feedbag – I/O Redirection in BASH (1) Pipes We've already seen pipes, but to recap the syntax: <command 1> | <command 2> ➔ Takes stdout of command 1 and pipes it into command 2 z.B. : Four parameters in simplewave.f90 – A (bias), w (freq), d (phz), N (samples) echo “$A $w $d $N” | ./simplewave (2) File Redirection Used to write stdout to a file: command > output file → Overwrites existing file. command >> output file → Appends to existing file. Additional C­like command for redirecting stdin from file: command < input file Often, combined as command < input file > output file command1 | command2 | command3 > output file The last (and most useful) I/O redirection method gets it's own section.... The Plow – Advanced I/O in BASH: HERE Blocks The Plow – Advanced I/O in BASH: HERE Blocks The Problems: Suppose I want to write several lines to a file. Why should I have to write “>> file” for multiple lines? ➢ Suppose I want one script to do everything: ➢ ­ Check code compilation ­ Get inputs from user or parameter lists ­ Create SGE submission scripts ­ Submit jobs ­ Run any post­processing code ­ xmgrace the output The (Very Simple) Solution: ➢ Include a HERE statement block – combo of redirections, EOF (end of file) and a 'cat'. ( cat <<EOF …commands… EOF ) >> output file The command list can include anything, including variables...thus, WARNING: Be careful with variables in HERE statement block.... WARNING: The Plow – Advanced I/O in BASH: HERE Blocks, cont. The Plow – Advanced I/O in BASH: HERE Blocks, cont. BASH Script = List of Linux Terminal (“Shell”) Commands, begins with #!/<path to bash> Simple Example – Our First Submission Script Sharp + Bang = “Shebang”! Whatever command follows shebang will run before the script itself. ­ Useful for 'pre­scripts'. Loop Start: Read in parameters from file. Alternately, can use shell math or user input (read statement). First lines of the submission script: shebang and grid engine setup. S.G.E. options: #$ Typical submission script: (1) Descend to working directory. (2) Pipe in run parameters to executable. (3) Move (if needed) the results. Submit to the queue! TAKE NOTE OF PREVIOUS WARNING: What if we had “cd $rundir” → What would happen? Hint: Don't forget to “chmod 755” your scripts! The Hitch­Tongue – S.G.E. Job Task Arrays The Hitch­Tongue – S.G.E. Job Task Arrays Sun Grid Engine ­ Job Task Arrays: One of the most useful SGE options is the “­t” option, which allows for 'true' distribution. “Turn the Knob” Philosophy Typically, we have a fixed set of parameters, and vary one. The task array allows one script to address ALL the values of the variable parameter. (z.B. a disorder realization!). Why would I want to use it? ­ A Typical qstat output job­ID prior name user state submit/start at queue slots ja­task­ID ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­ 857655 0.50243 freq_run bodyfelt t 02/04/2010 21:22:30 pallas@pallas02.mpipks­dresden 1 4 857655 0.50122 freq_run bodyfelt t 02/04/2010 21:22:30 tycho@tycho28.mpipks­dresden.m 1 5 857655 0.50081 freq_run bodyfelt t 02/04/2010 21:22:30 tycho@tycho26.mpipks­dresden.m 1 6 857655 0.50061 freq_run bodyfelt t 02/04/2010 21:22:30 brahe@brahe05.mpipks­dresden.m 1 7 857655 0.50049 freq_run bodyfelt t 02/04/2010 21:22:30 merkur@merkur01.mpipks­dresden 1 8 857655 0.50041 freq_run bodyfelt t 02/04/2010 21:22:30 rhea@rhea15.mpipks­dresden.mpg 1 9 857655 0.50035 freq_run bodyfelt qw 02/04/2010 21:22:01 1 10 How it works: (1) Set the SGE option: #$ ­t 1­<array size> (2) At runtime, internal shell variable is created: $SGE_TASK_ID (3) You can then use bc on $SGE_TASK_ID to get varying parameter values.... http://wiki.gridengine.info/wiki/index.php/Main_Page The Hitch­Tongue – S.G.E. Job Task Arrays, cont. The Hitch­Tongue – S.G.E. Job Task Arrays, cont. Simple Example – Task Array Submission Script ....YET AGAIN.... DON'T BE STUPID! Pay attention to $variable vs. \$variable The Sowed Field – HERE & gracebat scripting The Sowed Field – HERE & gracebat scripting http://plasma­gate.weizmann.ac.il/Grace/ Setup the axes, fonts, titles, etc. Everything but loading data. “Bodyfelt Custom Shop” Script: 256 x RGB colormap to grace Loading data. Same as xmgrace's Import ASCII > Load as Block Data And then some. Without clicking. Compile grace batch. Output in xmgrace. Same idea can be applied to most command line graphics (gnuplot, pgplot, wave, etc.) The Sowed Field – HERE & gracebat scripting, cont. The Sowed Field – HERE & gracebat scripting, cont. Conclusion Conclusion One last word regarding scripting... One last word regarding scripting... Повторение ­ мать учения. ➢ ➢ ➢ ➢ ➢ La práctica hace un santo. Übung macht den Meister. Άγιος που δε θαυματουργεί, μηδέ δοξολογιέται.