From c219b8dc7d5f24c4347fd368d79294e4fc70e9fe Mon Sep 17 00:00:00 2001 From: Remi Lehe Date: Tue, 21 Jul 2020 10:41:20 -0700 Subject: [PATCH 1/6] Avoid recompiling previous tests This is done by: - Storing compiled executable into a new "Build" folder - When running a new tests, comparing compiling options to those used in previous tests; it they match, the previous executable is retrieved from the Build folder. Note: this assumes that each executable name is unique ; i.e. that two sets of compiling options cannot produce the same executable name. In order to obtain the string that contains compiling options, part of the function `build_c` was extracted as a separate function --- regtest.py | 50 +++++++++++++++++++++++++++++++++++++++----------- suite.py | 11 +++++++++-- 2 files changed, 48 insertions(+), 13 deletions(-) diff --git a/regtest.py b/regtest.py index 18ba975..90c6b9b 100755 --- a/regtest.py +++ b/regtest.py @@ -49,15 +49,15 @@ def find_build_dirs(tests): last_safe = False for obj in tests: - + # keep track of the build directory and which source tree it is # in (e.g. the extra build dir) - + # first find the list of unique build directories dir_pair = (obj.buildDir, obj.extra_build_dir) if build_dirs.count(dir_pair) == 0: build_dirs.append(dir_pair) - + # re-make all problems that specify an extra compile argument, # and the test that comes after, just to make sure that any # unique build commands are seen. @@ -67,9 +67,9 @@ def find_build_dirs(tests): obj.reClean = 0 else: last_safe = True - + return build_dirs - + def cmake_setup(suite): "Setup for cmake" @@ -516,6 +516,10 @@ def test_suite(argv): # if ( suite.useCmake ): bdir = suite.source_build_dir os.chdir(bdir) + # Create directory for executables + binDir = 'Bin' + if not os.path.exists(binDir): + os.mkdir(binDir) if test.reClean == 1: # for one reason or another, multiple tests use different @@ -536,14 +540,38 @@ def test_suite(argv): coutfile = "{}/{}.make.out".format(output_dir, test.name) if suite.sourceTree == "C_Src" or test.testSrcTree == "C_Src": - if suite.useCmake: - comp_string, rc = suite.build_test_cmake(test=test, outfile=coutfile) - else: - comp_string, rc = suite.build_c(test=test, outfile=coutfile) - executable = test_util.get_recent_filename(bdir, "", ".ex") + # First check whether an executable was already compiled with + # the same options (not enabled for CMake, for now) + found_previous_test = False + if not suite.useCmake: + comp_string = suite.get_comp_string_c(test=test, outfile=coutfile) + # Loop over the existing tests + for previous_test in test_list: + # Check if the compile command was the same + if previous_test.comp_string == comp_string: + found_previous_test = True + break + + # Avoid recompiling in this case + if found_previous_test: + suite.log.log("found pre-built executable for this test") + rc = 0 + executable = previous_test.executable + # Otherwise recompile + else: + if suite.useCmake: + comp_string, rc = suite.build_test_cmake(test=test, outfile=coutfile) + else: + comp_string, rc = suite.build_c(test=test, outfile=coutfile) + executable = test_util.get_recent_filename(bdir, "", ".ex") + # Copy executable to bin directory (to avoid recompiling for other tests) + if executable is not None: + shutil.copy( executable, binDir ) test.comp_string = comp_string + # Register name of the executable + test.executable = executable # make return code is 0 if build was successful if rc == 0: @@ -572,7 +600,7 @@ def test_suite(argv): needed_files = [] if executable is not None: - needed_files.append((executable, "move")) + needed_files.append((os.path.join(binDir,executable), "copy")) if test.run_as_script: needed_files.append((test.run_as_script, "copy")) diff --git a/suite.py b/suite.py index f258402..dba1c01 100644 --- a/suite.py +++ b/suite.py @@ -114,6 +114,7 @@ def __init__(self, name): self.nlevels = None # set but running fboxinfo on the output self.comp_string = None # set automatically + self.executable = None # set automatically self.run_command = None # set automatically self.job_info_field1 = "" @@ -879,8 +880,8 @@ def make_realclean(self, repo="source"): test_util.run(cmd) - def build_c(self, test=None, opts="", target="", outfile=None, c_make_additions=None): - + def get_comp_string_c(self, test=None, opts="", target="", + outfile=None, c_make_additions=None): build_opts = "" if c_make_additions is None: c_make_additions = self.add_to_c_make_command @@ -911,6 +912,12 @@ def build_c(self, test=None, opts="", target="", outfile=None, c_make_additions= self.MAKE, self.numMakeJobs, self.amrex_dir, all_opts, self.COMP, c_make_additions, target) + return comp_string + + def build_c(self, test=None, opts="", target="", + outfile=None, c_make_additions=None): + comp_string = self.get_comp_string_c( test, opts, target, + outfile, c_make_additions ) self.log.log(comp_string) stdout, stderr, rc = test_util.run(comp_string, outfile=outfile) From dad5df09a298125db9e74af526ce0c3571833dd7 Mon Sep 17 00:00:00 2001 From: Remi Lehe Date: Sun, 26 Jul 2020 21:38:30 -0700 Subject: [PATCH 2/6] Add option to avoid recompiling --- regtest.py | 2 +- suite.py | 2 ++ test_util.py | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/regtest.py b/regtest.py index 90c6b9b..7655078 100755 --- a/regtest.py +++ b/regtest.py @@ -544,7 +544,7 @@ def test_suite(argv): # First check whether an executable was already compiled with # the same options (not enabled for CMake, for now) found_previous_test = False - if not suite.useCmake: + if test.avoid_recompiling and not suite.useCmake: comp_string = suite.get_comp_string_c(test=test, outfile=coutfile) # Loop over the existing tests for previous_test in test_list: diff --git a/suite.py b/suite.py index dba1c01..7732323 100644 --- a/suite.py +++ b/suite.py @@ -344,6 +344,7 @@ def set_runs_to_average(self, value): # Static member variables, set explicitly in apply_args in Suite class compile_only = False + avoid_recompiling = False skip_comparison = False global_tolerance = None global_particle_tolerance = None @@ -1076,6 +1077,7 @@ def apply_args(self): args = self.args Test.compile_only = args.compile_only + Test.avoid_recompiling = args.avoid_recompiling Test.skip_comparison = args.skip_comparison Test.global_tolerance = args.tolerance Test.global_particle_tolerance = args.particle_tolerance diff --git a/test_util.py b/test_util.py index d26fed0..c98bedb 100644 --- a/test_util.py +++ b/test_util.py @@ -343,6 +343,8 @@ def get_args(arg_string=None): "options that control how the tests are run") run_group.add_argument("--compile_only", action="store_true", help="test only that the code compiles, without running anything") + run_group.add_argument("--avoid_recompiling", action="store_true", + help="avoid recompiling, if an executable was already build with the same compilation options, in a previous test") run_group.add_argument("--with_valgrind", action="store_true", help="run with valgrind") run_group.add_argument("--valgrind_options", type=str, default="--leak-check=yes --log-file=vallog.%p", From 4c3be3bb79feee875cc666238f507a691e66f8a0 Mon Sep 17 00:00:00 2001 From: Remi Lehe Date: Sun, 26 Jul 2020 22:02:29 -0700 Subject: [PATCH 3/6] Create make.out file, even without recompilation --- regtest.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/regtest.py b/regtest.py index 7655078..533977f 100755 --- a/regtest.py +++ b/regtest.py @@ -556,6 +556,8 @@ def test_suite(argv): # Avoid recompiling in this case if found_previous_test: suite.log.log("found pre-built executable for this test") + with open(coutfile, "a") as cf: + cf.write("found pre-built executable for this test\n") rc = 0 executable = previous_test.executable # Otherwise recompile @@ -566,7 +568,7 @@ def test_suite(argv): comp_string, rc = suite.build_c(test=test, outfile=coutfile) executable = test_util.get_recent_filename(bdir, "", ".ex") # Copy executable to bin directory (to avoid recompiling for other tests) - if executable is not None: + if test.avoid_recompiling and executable is not None: shutil.copy( executable, binDir ) test.comp_string = comp_string From 0fc389d34d4b306903b2e9080509ccc3c1710ec4 Mon Sep 17 00:00:00 2001 From: Remi Lehe Date: Mon, 27 Jul 2020 08:13:11 -0700 Subject: [PATCH 4/6] Make one unique directory for each set of compilation option --- regtest.py | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/regtest.py b/regtest.py index 533977f..9396262 100755 --- a/regtest.py +++ b/regtest.py @@ -516,10 +516,10 @@ def test_suite(argv): # if ( suite.useCmake ): bdir = suite.source_build_dir os.chdir(bdir) - # Create directory for executables - binDir = 'Bin' - if not os.path.exists(binDir): - os.mkdir(binDir) + # Create directory for previously-compiled executables + precompiled_dir = 'PreviouslyCompiled' + if not os.path.exists(precompiled_dir): + os.mkdir(precompiled_dir) if test.reClean == 1: # for one reason or another, multiple tests use different @@ -567,9 +567,15 @@ def test_suite(argv): else: comp_string, rc = suite.build_c(test=test, outfile=coutfile) executable = test_util.get_recent_filename(bdir, "", ".ex") - # Copy executable to bin directory (to avoid recompiling for other tests) + # Store the executable (to avoid recompiling for other tests) if test.avoid_recompiling and executable is not None: - shutil.copy( executable, binDir ) + # Create a unique directory for these compilations options, + # by using the hash of the compilation options as the directory name + dir_name = os.path.join( precompiled_dir, hash(comp_string) ) + if not os.path.exists( dir_name ): + os.mkdir(dir_name) + # Copy the executable + shutil.copy( executable, dir_name ) test.comp_string = comp_string # Register name of the executable @@ -602,7 +608,12 @@ def test_suite(argv): needed_files = [] if executable is not None: - needed_files.append((os.path.join(binDir,executable), "copy")) + if test.avoid_recompiling: + # Find unique directory where the executable is stored + dir_name = os.path.join( precompiled_dir, hash(test.comp_string) ) + needed_files.append((os.path.join(dir_name,executable), "copy")) + else: + needed_files.append((executable, "move")) if test.run_as_script: needed_files.append((test.run_as_script, "copy")) From 367905ceb4586cece111f21a15c35ef4f33c3a70 Mon Sep 17 00:00:00 2001 From: Remi Lehe Date: Mon, 27 Jul 2020 08:18:35 -0700 Subject: [PATCH 5/6] Avoid creating unused directory when the option is not used --- regtest.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/regtest.py b/regtest.py index 9396262..a07879d 100755 --- a/regtest.py +++ b/regtest.py @@ -516,10 +516,6 @@ def test_suite(argv): # if ( suite.useCmake ): bdir = suite.source_build_dir os.chdir(bdir) - # Create directory for previously-compiled executables - precompiled_dir = 'PreviouslyCompiled' - if not os.path.exists(precompiled_dir): - os.mkdir(precompiled_dir) if test.reClean == 1: # for one reason or another, multiple tests use different @@ -571,10 +567,12 @@ def test_suite(argv): if test.avoid_recompiling and executable is not None: # Create a unique directory for these compilations options, # by using the hash of the compilation options as the directory name - dir_name = os.path.join( precompiled_dir, hash(comp_string) ) + if not os.path.exists('PreviouslyCompiled'): + os.mkdir('PreviouslyCompiled') + dir_name = os.path.join( 'PreviouslyCompiled', hash(comp_string) ) if not os.path.exists( dir_name ): os.mkdir(dir_name) - # Copy the executable + # Copy the executable to that unique directory shutil.copy( executable, dir_name ) test.comp_string = comp_string @@ -610,7 +608,7 @@ def test_suite(argv): if executable is not None: if test.avoid_recompiling: # Find unique directory where the executable is stored - dir_name = os.path.join( precompiled_dir, hash(test.comp_string) ) + dir_name = os.path.join( 'PreviouslyCompiled', hash(test.comp_string) ) needed_files.append((os.path.join(dir_name,executable), "copy")) else: needed_files.append((executable, "move")) From 6e99ce0121a9451fa3720c56d36214211cf478ae Mon Sep 17 00:00:00 2001 From: Remi Lehe Date: Mon, 27 Jul 2020 08:31:49 -0700 Subject: [PATCH 6/6] Fix type of directory name --- regtest.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/regtest.py b/regtest.py index a07879d..c321bf3 100755 --- a/regtest.py +++ b/regtest.py @@ -569,7 +569,7 @@ def test_suite(argv): # by using the hash of the compilation options as the directory name if not os.path.exists('PreviouslyCompiled'): os.mkdir('PreviouslyCompiled') - dir_name = os.path.join( 'PreviouslyCompiled', hash(comp_string) ) + dir_name = os.path.join( 'PreviouslyCompiled', str(hash(comp_string)) ) if not os.path.exists( dir_name ): os.mkdir(dir_name) # Copy the executable to that unique directory @@ -608,7 +608,7 @@ def test_suite(argv): if executable is not None: if test.avoid_recompiling: # Find unique directory where the executable is stored - dir_name = os.path.join( 'PreviouslyCompiled', hash(test.comp_string) ) + dir_name = os.path.join( 'PreviouslyCompiled', str(hash(test.comp_string)) ) needed_files.append((os.path.join(dir_name,executable), "copy")) else: needed_files.append((executable, "move"))