← Back to team overview

dolfin team mailing list archive

Re: Buildbots

 

>
>  Also, scaling down the slowest demos and maybe let the regression test
> runner be threaded might cut down the check time a lot.
>

I've attached a patch for test/regression/test.py that runs two tests at a
time (unless the mpirun prefix is set, when only one thread is used). The
number of threads (2) is hardcoded, look for "threading.Semaphore(2 ...)" to
change. Might shave off a few minutes.

-j.
diff --git a/test/regression/test.py b/test/regression/test.py
index 2c1dbd6..f36852a 100644
--- a/test/regression/test.py
+++ b/test/regression/test.py
@@ -14,6 +14,7 @@ import platform
 from time import time
 from dolfin_utils.commands import getstatusoutput
 from dolfin import has_mpi, has_parmetis
+import threading
 
 # Location of all demos
 demodir = os.path.join(os.curdir, "..", "..", "demo")
@@ -39,23 +40,14 @@ print "Found %d Python demos" % len(pydemos)
 print ""
 import pprint
 
-# Remove demos that are known not to work (FIXME's)
-#pydemos.remove(os.path.join(demodir, 'undocumented', 'aliev-panfilov', 'python'))
-#pydemos.remove(os.path.join(demodir, 'undocumented', 'lorenz', 'python'))
-
-# Push slow demos to the end
-pyslow = []
-cppslow = []
-for s in pyslow:
-    pydemos.remove(s)
-    pydemos.append(s)
-for s in cppslow:
-    cppdemos.remove(s)
-    cppdemos.append(s)
-
 # Remove overly slow demos
 #cppdemos.remove(os.path.join(demodir, 'undocumented', 'elastodynamics', 'cpp'))
 
+# Push slow demos to the front (of the python list, which runs last), so that we
+# don't have to wait for them in the end when there's nothing else to run.
+pydemos.remove(   os.path.join(demodir,  'pde', 'cahn-hilliard', 'python'))
+pydemos.insert(0, os.path.join(demodir,  'pde', 'cahn-hilliard', 'python'))
+
 # Remove demos that need command-line arguments
 pydemos.remove(os.path.join(demodir,  'undocumented', 'quadrature', 'python'))
 cppdemos.remove(os.path.join(demodir, 'undocumented', 'quadrature', 'cpp'))
@@ -83,55 +75,70 @@ if "RUN_UNIT_TESTS_IN_PARALLEL" in os.environ and has_mpi() and has_parmetis():
 else:
     print "Not running regression tests in parallel."
 
+class Runner(object):
+    def __init__(self, typ, prefix, demo, cmd):
+        global run_semaphore
+        run_semaphore.acquire()
+        self.typ = typ
+        self.prefix = prefix
+        self.demo = demo
+        self.name = "%s/%s" % (prefix, demo)
+        self.cmd = cmd
+
+    def __call__(self):
+        global timing, failed, run_semaphore
+        try:
+            print "Running %s demo %s" % (self.typ, self.name)
+            T = time()
+            output = getstatusoutput(self.cmd)
+            T = time()-T
+
+            timing += [(T, self.demo)]
+
+            if output[0] == 0:
+                print "    OK: %s demo %s" % (self.typ, self.name)
+            elif output[0] == 10: # Failing but exiting gracefully
+                print "  (ok): %s demo %s (graceful exit on fail)" % (self.typ, self.name)
+            else:
+                failed += [(self.demo, self.typ, self.prefix, output[1])]
+                print "**FAIL: %s demo %s:\n%s" % (self.typ, self.name, output[1])
+        finally:
+            run_semaphore.release()
+
 # Run in serial, then in parallel
 for prefix in prefixes:
 
+    # Number of tests to run at the same time (active threads)
+    global run_semaphore
+    run_semaphore = threading.Semaphore(2 if prefix=='' else 1)
+
     # Run C++ demos
     for demo in cppdemos:
-        print "----------------------------------------------------------------------"
-        print "Running C++ demo %s%s" % (prefix, demo)
-        print ""
         cppdemo_ext = ''
         if platform.system() == 'Windows':
             cppdemo_ext = '.exe'
         cppdemo_prefix = demo.split(os.path.sep)[-2]
         if os.path.isfile(os.path.join(demo, cppdemo_prefix + '-demo' + cppdemo_ext)):
-            t1 = time()
-            output = getstatusoutput("cd %s && %s .%s%s-demo%s" % \
-                                         (demo, prefix, os.path.sep, cppdemo_prefix, cppdemo_ext))
-            t2 = time()
-            timing += [(t2 - t1, demo)]
-            if output[0] == 0:
-                print "OK"
-            elif output[0] == 10: # Failing but exiting gracefully
-                print "ok (graceful exit on fail)"
-            else:
-                print "*** Failed"
-                print output[1]
-                failed += [(demo, "C++", prefix, output[1])]
+            runner = Runner("C++", prefix, demo,
+                            "cd %s && %s .%s%s-demo%s" % \
+                                (demo, prefix, os.path.sep, cppdemo_prefix, cppdemo_ext))
+            threading.Thread(target=runner).start()
         else:
-            print "*** Warning: missing demo"
+            print "**WARN: missing C++ demo %s/%s" % (prefix, demo)
 
     # Run Python demos
     for demo in pydemos:
-        print "----------------------------------------------------------------------"
-        print "Running Python demo %s%s" % (prefix, demo)
-        print ""
         if os.path.isfile(os.path.join(demo, 'demo.py')):
-            t1 = time()
-            output = getstatusoutput("cd %s && %s python demo.py" % (demo, prefix))
-            t2 = time()
-            timing += [(t2 - t1, demo)]
-            if output[0] == 0:
-                print "OK"
-            elif output[0] == 10: # Failing but exiting gracefully
-                print "ok (graceful exit on fail)"
-            else:
-                print "*** Failed"
-                print output[1]
-                failed += [(demo, "Python", prefix, output[1])]
+            runner = Runner("Python", prefix, demo,
+                            "cd %s && %s python demo.py" % (demo, prefix))
+            threading.Thread(target=runner).start()
         else:
-            print "*** Warning: missing demo"
+            print "**WARN: missing Python demo %s/%s" % (prefix, demo)
+
+    # Wait for all outstanding threads, because afterwards we either switch semaphore or exit.
+    for thread in threading.enumerate():
+        if thread is not threading.current_thread():
+            thread.join()
 
 # Print summary of time to run demos
 timing.sort()

References