/src/app/wavesim2D/F77/autoedit.py

https://github.com/freephys/Langtangen · Python · 165 lines · 158 code · 3 blank · 4 comment · 0 complexity · a47025caa857fbd09ff75b011bb7aa4e MD5 · raw file

  1. #!/usr/bin/env python
  2. # automatic execution of HPC exercises
  3. import shutil, sys, os, re, glob
  4. counter = 0
  5. def edit(from_to, filename='F77WAVE.fcp'):
  6. """
  7. substitute (from,to) in from_to list, e.g.
  8. edit((r'from',r'to'))
  9. """
  10. shutil.copy(filename + ".orig", filename)
  11. f = open(filename, 'r')
  12. filestr = f.read() # read file into memory
  13. f.close()
  14. for (from_, to) in from_to:
  15. c = re.compile(from_, re.MULTILINE)
  16. filestr = c.sub(to, filestr)
  17. f = open(filename, 'w')
  18. f.write(filestr)
  19. f.close()
  20. global counter
  21. shutil.copy(filename, filename + str(counter)); counter += 1
  22. def compile(compiler, options):
  23. # run C preprocessor on F77WAVE.fcp and create F77WAVE.f:
  24. os.system("./fcpp.py F77WAVE.fcp")
  25. # compile and link:
  26. cmd = "%s %s -pg -o app F77WAVE.f main.f" % (compiler, options)
  27. print cmd
  28. os.system(cmd)
  29. def write_results(message, file):
  30. file.write("\n\n-----------------------------------------------\n")
  31. file.write(">>>> " + message + "\n")
  32. # extract table from the output of gprof
  33. res = os.popen("gprof app")
  34. lines = res.readlines()
  35. res.close()
  36. # grab table:
  37. m = re.search(r"(\% cumulative.*)\%\s+the percentage of the total",
  38. ''.join(lines), re.DOTALL)
  39. if m:
  40. table = m.group(1)
  41. file.write(table)
  42. # write the current version F77WAVE.f:
  43. f = open('F77WAVE.f', 'r'); filestr = f.read(); f.close()
  44. file.write("\n*** current version of F77WAVE.f ***\n")
  45. file.write(filestr)
  46. file.write("************\n\n")
  47. # extract CPU time and return
  48. for line in lines:
  49. if re.search(r"MAIN__$", line):
  50. cpu_time = float(line.split()[1])
  51. break
  52. print message, cpu_time, "sec"
  53. return cpu_time
  54. def run():
  55. #print "running app..."
  56. #os.system("app > /dev/null")
  57. os.system("app")
  58. def test_IO(compiler, options):
  59. message = "with I/O (call dump)"
  60. edit(((r"^C(\s+)call dump", r" \1call dump"),), filename="main.f")
  61. compile(compiler, options)
  62. run()
  63. cpu = write_results(message, resultfile)
  64. compactresults.append((message, cpu))
  65. # back to normal files:
  66. shutil.copy('main.f.orig', 'main.f')
  67. shutil.copy('F77WAVE.fcp.orig', 'F77WAVE.fcp')
  68. # clean up the big files:
  69. tmpfiles = glob.glob('tmp_*')
  70. for file in tmpfiles: os.remove(file)
  71. def test_Olevels(compiler, options):
  72. for i in range(0,4,1):
  73. message = "with optimization level -O%d" % i
  74. compile(compiler, options + " -O%d " % i)
  75. run()
  76. cpu = write_results(message, resultfile)
  77. compactresults.append((message, cpu))
  78. def test_loop_unrolling(compiler, options):
  79. message = "loop unrolling (by the compiler)"
  80. compile(compiler, options + " -funroll-loops ")
  81. run()
  82. cpu = write_results(message, resultfile)
  83. compactresults.append((message, cpu))
  84. def test_swap_loops(compiler, options):
  85. message = "traverse arrays column by column"
  86. edit(((r"DO 20 j = 2, ny-1", r"DO 20 i = 2, nx-1"),
  87. (r"DO 10 i = 2, nx-1", r"DO 10 j = 2, ny-1")))
  88. compile(compiler, options)
  89. run()
  90. cpu = write_results(message, resultfile)
  91. compactresults.append((message, cpu))
  92. def test_callfunc1(compiler, options):
  93. message = "lambda(i,j) replaced by function call h(0,0)"
  94. edit(((r"lambda\(([^,]+),([^)]+)\)", r"h(0,0)"),
  95. (r"REAL\*8 a, b, c", r"REAL*8 a, b, c, h"),
  96. (r", h\(0,0\)", r"")))
  97. compile(compiler, options)
  98. run()
  99. cpu = write_results(message, resultfile)
  100. compactresults.append((message, cpu))
  101. def test_callfunc2(compiler, options):
  102. message = "lambda(i,j) replaced by function call h((i-1)*delta,(j-1)*delta)"
  103. edit(((r"lambda\(([^,]+),([^)]+)\)", r"h((\1 -1)*delta,(\2 -1)*delta)"),
  104. (r"REAL\*8 a, b, c", r"REAL*8 a, b, c, h, delta"),
  105. (r"INTEGER i,j", r"INTEGER i,j\n delta = 10.0/(nx-1)"),
  106. (r", h\(\(nx .*$", r"")))
  107. compile(compiler, options)
  108. run()
  109. cpu = write_results(message, resultfile)
  110. compactresults.append((message, cpu))
  111. def test_iftests_in_loops(compiler, options):
  112. message = "if-tests inside loops"
  113. edit(((r"DO 20 j = 2, ny-1", r"DO 20 j = 1, ny"),
  114. (r"DO 10 i = 2, nx-1", r"DO 10 i = 1, nx\n if (i .ge. 2 .and. i .le. nx-1 .and. j .ge. 2 \n > .and. j .le. ny-1) then"),
  115. (r"10 CONTINUE", r" end if\n 10 CONTINUE")))
  116. compile(compiler, options)
  117. run()
  118. cpu = write_results(message, resultfile)
  119. compactresults.append((message, cpu))
  120. #---------------------------------------------------------------------------
  121. # run exercises:
  122. resultfile = open('results', 'w')
  123. compactresults = []
  124. # make sure we start with the right files:
  125. shutil.copy('main.f.orig', 'main.f')
  126. shutil.copy('F77WAVE.fcp.orig', 'F77WAVE.fcp')
  127. #print "test1:"
  128. #test_iftests_in_loops('g77', '-O3')
  129. #sys.exit(1)
  130. tests = [test_IO, test_Olevels, test_loop_unrolling,
  131. test_swap_loops, test_callfunc1, test_callfunc2,
  132. test_iftests_in_loops]
  133. #tests = [test_loop_unrolling,
  134. # test_callfunc1, test_callfunc2, test_iftests_in_loops]
  135. for compiler in ['g77']:
  136. for options in ['-O3']:
  137. for test in tests:
  138. test(compiler, options)
  139. resultfile.close()
  140. # write a compact table with the main results:
  141. print "\n\n\n"
  142. for (case, cpu) in compactresults:
  143. print "%-65s %10.3f" % (case, cpu)