Bläddra i källkod

Create the adaptive-jit-favor-loops kernel, make it the default

jonathanvdc 8 år sedan
förälder
incheckning
24a9339ea6

+ 8 - 2
hybrid_server/classes/mvkcontroller.xml

@@ -40,12 +40,18 @@
                     self.mvk.jit.set_function_body_compiler(jit.compile_function_body_fast)
                 elif opt == 'baseline-jit':
                     self.mvk.jit.set_function_body_compiler(jit.compile_function_body_baseline)
-                elif opt == 'adaptive-jit' or opt == 'adaptive-jit-favor-large-functions':
-                    self.mvk.jit.set_function_body_compiler(jit.compile_function_body_adaptive)
+                elif opt == 'adaptive-jit-favor-large-functions':
+                    self.mvk.jit.set_function_body_compiler(
+                            lambda *args: jit.compile_function_body_adaptive(
+                                *args, temperature_heuristic=jit.favor_large_functions))
                 elif opt == 'adaptive-jit-favor-small-functions':
                     self.mvk.jit.set_function_body_compiler(
                         lambda *args: jit.compile_function_body_adaptive(
                             *args, temperature_heuristic=jit.favor_small_functions))
+                elif opt == 'adaptive-jit' or opt == 'adaptive-jit-favor-loops':
+                    self.mvk.jit.set_function_body_compiler(
+                        lambda *args: jit.compile_function_body_adaptive(
+                            *args, temperature_heuristic=jit.favor_loops))
                 else:
                     print("warning: unknown kernel option '%s'." % opt)
 

+ 10 - 2
kernel/modelverse_jit/bytecode_ir.py

@@ -7,7 +7,8 @@ class Instruction(object):
         self.debug_information = None
 
     def get_directly_reachable(self):
-        """Gets all instructions that are directly reachable from this instruction."""
+        """Gets all instructions that are directly reachable from this instruction, excluding the
+           next instruction."""
         raise NotImplementedError()
 
     def get_reachable(self):
@@ -18,8 +19,12 @@ class Instruction(object):
         while len(stack) > 0:
             instr = stack.pop()
             results.add(instr)
+            next_instr = instr.next_instruction
+            if next_instr is not None and next_instr not in results:
+                stack.append(next_instr)
             for other in instr.get_directly_reachable():
                 if other not in results:
+                    assert other is not None
                     stack.append(other)
 
         return results
@@ -120,7 +125,10 @@ class ReturnInstruction(Instruction):
 
     def get_directly_reachable(self):
         """Gets all instructions that are directly reachable from this instruction."""
-        return (self.value,)
+        if self.value is None:
+            return ()
+        else:
+            return (self.value,)
 
     constructor_parameters = (('value', Instruction),)
 

+ 28 - 1
kernel/modelverse_jit/jit.py

@@ -4,6 +4,7 @@ import modelverse_kernel.primitives as primitive_functions
 import modelverse_jit.bytecode_parser as bytecode_parser
 import modelverse_jit.bytecode_to_tree as bytecode_to_tree
 import modelverse_jit.bytecode_to_cfg as bytecode_to_cfg
+import modelverse_jit.bytecode_ir as bytecode_ir
 import modelverse_jit.cfg_optimization as cfg_optimization
 import modelverse_jit.cfg_to_tree as cfg_to_tree
 import modelverse_jit.cfg_ir as cfg_ir
@@ -806,12 +807,37 @@ def favor_small_functions(body_bytecode):
             '+',
             tree_ir.LiteralInstruction(1)))
 
+ADAPTIVE_JIT_LOOP_INSTRUCTION_MULTIPLIER = 4
+
 ADAPTIVE_FAST_JIT_TEMPERATURE_THRESHOLD = 200
 """The threshold temperature at which fast-jit will be used."""
 
+def favor_loops(body_bytecode):
+    """Computes the initial temperature of a function. Code within a loop makes
+       the function hotter; code outside loops makes the function colder. The
+       temperature is incremented by one on every call."""
+    reachable_instructions = body_bytecode.get_reachable()
+    # First set the temperature to the negative number of instructions.
+    temperature = ADAPTIVE_FAST_JIT_TEMPERATURE_THRESHOLD - len(reachable_instructions)
+    for instruction in reachable_instructions:
+        if isinstance(instruction, bytecode_ir.WhileInstruction):
+            # Then increase the temperature by the number of instructions reachable
+            # from loop bodies. Note that the algorithm will count nested loops twice.
+            # This is actually by design.
+            loop_body_instructions = instruction.body.get_reachable()
+            temperature += ADAPTIVE_JIT_LOOP_INSTRUCTION_MULTIPLIER * len(loop_body_instructions)
+
+    return (
+        temperature,
+        lambda old_value:
+        tree_ir.BinaryInstruction(
+            old_value,
+            '+',
+            tree_ir.LiteralInstruction(1)))
+
 def compile_function_body_adaptive(
         jit, function_name, body_id, task_root,
-        temperature_heuristic=favor_large_functions):
+        temperature_heuristic=favor_loops):
     """Compile the function with the given name and body id. An execution engine is picked
        automatically, and the function may be compiled again at a later time."""
     # The general idea behind this compilation technique is to first use the baseline JIT
@@ -821,6 +847,7 @@ def compile_function_body_adaptive(
 
     body_bytecode, = yield [("CALL_ARGS", [jit.jit_parse_bytecode, (body_id,)])]
     initial_temperature, increment_temperature = temperature_heuristic(body_bytecode)
+    print('Initial temperature for %s: %d' % (function_name, initial_temperature))
 
     if initial_temperature >= ADAPTIVE_FAST_JIT_TEMPERATURE_THRESHOLD:
         # Initial temperature exceeds the fast-jit threshold.

+ 7 - 1
performance/utils.py

@@ -30,12 +30,18 @@ OPTIMIZATION_LEVEL_INTERPRETER = "interpreter"
 OPTIMIZATION_LEVEL_BASELINE_JIT = "baseline-jit"
 OPTIMIZATION_LEVEL_BASELINE_JIT_NO_THUNKS = "baseline-jit,no-thunks"
 OPTIMIZATION_LEVEL_FAST_JIT = "fast-jit"
+OPTIMIZATION_LEVEL_ADAPTIVE_JIT_FAVOR_LARGE_FUNCTIONS = "adaptive-jit-favor-large-functions"
+OPTIMIZATION_LEVEL_ADAPTIVE_JIT_FAVOR_SMALL_FUNCTIONS = "adaptive-jit-favor-small-functions"
+OPTIMIZATION_LEVEL_ADAPTIVE_JIT_FAVOR_LOOPS = "adaptive-jit-favor-loops"
 ALL_OPTIMIZATION_LEVELS = [
     OPTIMIZATION_LEVEL_LEGACY_INTERPRETER,
     OPTIMIZATION_LEVEL_INTERPRETER,
     OPTIMIZATION_LEVEL_BASELINE_JIT,
     OPTIMIZATION_LEVEL_BASELINE_JIT_NO_THUNKS,
-    OPTIMIZATION_LEVEL_FAST_JIT
+    OPTIMIZATION_LEVEL_FAST_JIT,
+    OPTIMIZATION_LEVEL_ADAPTIVE_JIT_FAVOR_LARGE_FUNCTIONS,
+    OPTIMIZATION_LEVEL_ADAPTIVE_JIT_FAVOR_SMALL_FUNCTIONS,
+    OPTIMIZATION_LEVEL_ADAPTIVE_JIT_FAVOR_LOOPS
 ]
 
 class ModelverseTerminated(Exception):