changeset 1268:61ac5debba24

benchmark can be shortcut if needed_data are provided.
author Janus Dam Nielsen <janus.nielsen@alexandra.dk>
date Fri, 09 Oct 2009 13:04:18 +0200
parents 8d213ad683c2
children f91b28a6cbbe
files apps/benchmark.py
diffstat 1 files changed, 53 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/apps/benchmark.py	Fri Oct 09 13:04:18 2009 +0200
+++ b/apps/benchmark.py	Fri Oct 09 13:04:18 2009 +0200
@@ -146,10 +146,15 @@
                   help="skip local computations using fake field elements")
 parser.add_option("--args", type="string",
                   help="additional arguments to the runtime, the format is a comma separated list of id=value pairs e.g. --args s=1,d=0,lambda=1")
+parser.add_option("--needed_data", type="string",
+                  help="name of a file containing already computed dictionary of needed_data. Useful for skipping generating the needed data, which usually elliminates half the execution time. Format of file: \"{('random_triple', (Zp,)): [(3, 1), (3, 4)]}\"")
+parser.add_option("--pc", type="string",
+                  help="The program counter to start from when using explicitly provided needed_data. Format: [3,0]")
 
 parser.set_defaults(modulus=2**65, threshold=1, count=10,
                     runtime=runtimes.keys()[0], mixins="", num_players=2, prss=True,
-                    operation=operations.keys()[0], parallel=True, fake=False, args="")
+                    operation=operations.keys()[0], parallel=True, fake=False, 
+                    args="", needed_data="")
 
 print "*" * 60
 
@@ -178,28 +183,44 @@
 count = options.count
 print "I am player %d, will %s %d numbers" % (id, options.operation, count)
 
+
+class BenchmarkStrategy:
+
+    def benchmark(self, *args):
+        raise NotImplemented("Override this abstract method in subclasses")
+
+
+class SelfcontainedBenchmarkStrategy(BenchmarkStrategy):
+
+    def benchmark(self, *args):
+        sys.stdout.flush()
+        sync = self.rt.synchronize()
+        self.doTest(sync, lambda x: x)
+        self.rt.schedule_callback(sync, self.preprocess)
+        self.doTest(sync, lambda x: self.rt.shutdown())
+
+
+class NeededDataBenchmarkStrategy(BenchmarkStrategy):
+
+    def benchmark(self, needed_data, pc, *args):
+        self.pc = pc
+        sys.stdout.flush()
+        sync = self.rt.synchronize()
+        self.rt.schedule_callback(sync, lambda x: needed_data)
+        self.rt.schedule_callback(sync, self.preprocess)
+        self.doTest(sync, lambda x: self.rt.shutdown())
+
+
 # Defining the protocol as a class makes it easier to write the
 # callbacks in the order they are called. This class is a base class
 # that executes the protocol by calling the run_test method.
 class Benchmark:
 
     def __init__(self, rt, operation):
-        print "init"
         self.rt = rt
         self.operation = operation
         self.pc = None
-        sys.stdout.flush()
-        sync = self.rt.synchronize()
-        self.doTest(sync, lambda x: x)
-        self.rt.schedule_callback(sync, self.preprocess)
-        self.doTest(sync, lambda x: self.rt.shutdown())
         
-#     def sync_preprocess(self):
-#         print "Synchronizing preprocessing"
-#         sys.stdout.flush()
-#         sync = self.rt.synchronize()
-#         self.rt.schedule_callback(sync, self.preprocess)
-
     def preprocess(self, needed_data):
         print "Preprocess", needed_data
         if needed_data:
@@ -213,10 +234,8 @@
             return None
 
     def doTest(self, d, termination_function):
-        print "doTest", self.rt.program_counter
         self.rt.schedule_callback(d, self.begin)
         self.rt.schedule_callback(d, self.sync_test)
-#         self.rt.schedule_callback(d, self.countdown, 3)
         self.rt.schedule_callback(d, self.run_test)
         self.rt.schedule_callback(d, self.sync_test)
         self.rt.schedule_callback(d, self.finished, termination_function)
@@ -246,16 +265,6 @@
         self.rt.schedule_callback(sync, lambda y: x)
         return sync
 
-#     def countdown(self, _, seconds):
-#         if seconds > 0:
-#             print "Starting test in %d" % seconds
-#             sys.stdout.flush()
-#             reactor.callLater(1, self.countdown, None, seconds - 1)
-#         else:
-#             print "Starting test now"
-#             sys.stdout.flush()
-#             self.run_test(None)
-
     def run_test(self, _):
         raise NotImplemented("Override this abstract method in a sub class.")
 
@@ -286,6 +295,7 @@
             a = self.a_shares.pop()
             b = self.b_shares.pop()
             c_shares.append(self.operation(a, b))
+            print "."
 
         done = gather_shares(c_shares)
         done.addCallback(record_stop, "parallel test")
@@ -340,6 +350,20 @@
 else:
     benchmark = SequentialBenchmark
 
+needed_data = ""
+if options.needed_data != "":
+    file = open(options.needed_data, 'r')
+    for l in file:
+        needed_data += l
+    needed_data = eval(needed_data)
+
+if options.needed_data != "" and options.pc != "":
+    bases = (benchmark,) + (NeededDataBenchmarkStrategy,) + (object,)
+    options.pc = eval(options.pc)
+else:
+    bases = (benchmark,) + (SelfcontainedBenchmarkStrategy,) + (object,)
+benchmark = type("ExtendedBenchmark", bases, {})
+
 pre_runtime = create_runtime(id, players, options.threshold,
                              options, runtime_class)
 
@@ -355,7 +379,10 @@
 
 pre_runtime.addCallback(update_args, options)
 
-pre_runtime.addCallback(benchmark, operation)
+def do_benchmark(runtime, operation, benchmark, *args):
+    benchmark(runtime, operation).benchmark(*args)
+
+pre_runtime.addCallback(do_benchmark, operation, benchmark, needed_data, options.pc)
 
 print "#### Starting reactor ###"
 reactor.run()