def run(args, options): """ Compile a file and output a Program object. If options.merge_opens is set to True, will attempt to merge any parallelisable open instructions. """ prog = Program(args, options) VARS['program'] = prog if options.binary: VARS['sint'] = GC_types.sbitintvec.get_type(int(options.binary)) VARS['sfix'] = GC_types.sbitfixvec print('Compiling file', prog.infile) # make compiler modules directly accessible sys.path.insert(0, 'Compiler') # create the tapes exec(compile(open(prog.infile).read(), prog.infile, 'exec'), VARS) prog.finalize() if prog.req_num: print('Program requires:') for x in prog.req_num.pretty(): print(x) if prog.verbose: print('Program requires:', repr(prog.req_num)) print('Cost:', 0 if prog.req_num is None else prog.req_num.cost()) print('Memory size:', dict(prog.allocated_mem)) return prog
def run(args, options, param=-1, merge_opens=True, \ reallocate=True, debug=False): """ Compile a file and output a Program object. If merge_opens is set to True, will attempt to merge any parallelisable open instructions. """ prog = Program(args, options, param) instructions.program = prog instructions_base.program = prog types.program = prog comparison.program = prog prog.DEBUG = debug VARS['program'] = prog comparison.set_variant(options) print 'Compiling file', prog.infile if instructions_base.Instruction.count != 0: print 'instructions count', instructions_base.Instruction.count instructions_base.Instruction.count = 0 prog.FIRST_PASS = False prog.reset_values() # make compiler modules directly accessible sys.path.insert(0, 'Compiler') # create the tapes execfile(prog.infile, VARS) # optimize the tapes for tape in prog.tapes: tape.optimize(options) if prog.main_thread_running: prog.update_req(prog.curr_tape) print 'Program requires:', repr(prog.req_num) print 'Memory size:', prog.allocated_mem # finalize the memory prog.finalize_memory() return prog
def run(args, options, param=-1, merge_opens=True, reallocate=True, debug=False): """ Compile a file and output a Program object. If merge_opens is set to True, will attempt to merge any parallelisable open instructions. """ prog = Program(args, options, param) instructions.program = prog instructions_base.program = prog types.program = prog comparison.program = prog prog.DEBUG = debug VARS['program'] = prog if options.binary: VARS['sint'] = GC_types.sbitint.get_type(int(options.binary)) VARS['sfix'] = GC_types.sbitfix comparison.set_variant(options) print('Compiling file', prog.infile) if instructions_base.Instruction.count != 0: print('instructions count', instructions_base.Instruction.count) instructions_base.Instruction.count = 0 # make compiler modules directly accessible sys.path.insert(0, 'Compiler') # create the tapes exec(compile(open(prog.infile).read(), prog.infile, 'exec'), VARS) # optimize the tapes for tape in prog.tapes: tape.optimize(options) if prog.main_thread_running: prog.update_req(prog.curr_tape) if prog.req_num: print('Program requires:') for x in prog.req_num.pretty(): print(x) if prog.verbose: print('Program requires:', repr(prog.req_num)) print('Cost:', 0 if prog.req_num is None else prog.req_num.cost()) print('Memory size:', dict(prog.allocated_mem)) # finalize the memory prog.finalize_memory() return prog
def run(filename, options, param=-1, merge_opens=True, emulate=True, \ reallocate=True, assemblymode=False, debug=False): """ Compile a file and output a Program object. If merge_opens is set to True, will attempt to merge any parallelisable open instructions. """ prog = Program(filename, options, param, assemblymode) instructions.program = prog instructions_base.program = prog types.program = prog comparison.program = prog prog.EMULATE = emulate prog.DEBUG = debug VARS['program'] = prog comparison.set_variant(options) print 'Compiling file', prog.infile # no longer needed, but may want to support assembly in future (?) if assemblymode: prog.restart_main_thread() for i in xrange(INIT_REG_MAX): VARS['c%d'%i] = prog.curr_block.new_reg('c') VARS['s%d'%i] = prog.curr_block.new_reg('s') VARS['cg%d'%i] = prog.curr_block.new_reg('cg') VARS['sg%d'%i] = prog.curr_block.new_reg('sg') if i % 10000000 == 0 and i > 0: print "Initialized %d register variables at" % i, time.asctime() # first pass determines how many assembler registers are used prog.FIRST_PASS = True execfile(prog.infile, VARS) if instructions_base.Instruction.count != 0: print 'instructions count', instructions_base.Instruction.count instructions_base.Instruction.count = 0 prog.FIRST_PASS = False prog.reset_values() # make compiler modules directly accessible sys.path.insert(0, 'Compiler') # create the tapes execfile(prog.infile, VARS) # optimize the tapes for tape in prog.tapes: tape.optimize(options) # check program still does the same thing after optimizations if emulate: clearmem = list(prog.mem_c) sharedmem = list(prog.mem_s) prog.emulate() if prog.mem_c != clearmem or prog.mem_s != sharedmem: print 'Warning: emulated memory values changed after compiler optimization' # raise CompilerError('Compiler optimization caused incorrect memory write.') if prog.main_thread_running: prog.update_req(prog.curr_tape) print 'Program requires:', repr(prog.req_num) #print 'Cost:', prog.req_num.cost() print 'Memory size:', prog.allocated_mem # finalize the memory prog.finalize_memory() return prog
def main(): parser = argparse.ArgumentParser( description= "A compiler for generating arithmetic or GC circuits from .mpc files") parser.add_argument('filename', type=str, help="File name of the .mpc program") parser.add_argument("-p", "--party", dest="party", help="party number") parser.add_argument("-n", "--nomerge", action="store_false", dest="merge_opens", default=True, help="don't attempt to merge open instructions") parser.add_argument("-o", "--output", dest="outfile", help="specify output file") parser.add_argument("-a", "--asm-output", dest="asmoutfile", help="asm output file for debugging") parser.add_argument("-d", "--debug", action="store_true", dest="debug", help="keep track of trace for debugging") parser.add_argument("-c", "--comparison", dest="comparison", default="log", help="comparison variant: log|plain") parser.add_argument("-D", "--dead-code-elimination", action="store_true", dest="dead_code_elimination", default=False, help="eliminate instructions with unused result") parser.add_argument( "-r", "--noreorder", dest="reorder_between_opens", action="store_false", default=True, help="don't attempt to place instructions between start/stop opens") parser.add_argument( "-M", "--preserve-mem-order", action="store_true", dest="preserve_mem_order", default=False, help="preserve order of memory instructions; possible efficiency loss") parser.add_argument("-u", "--noreallocate", action="store_true", dest="noreallocate", default=False, help="don't reallocate") parser.add_argument("-m", "--max-parallel-open", dest="max_parallel_open", default=False, help="restrict number of parallel opens") parser.add_argument("-P", "--profile", action="store_true", dest="profile", help="profile compilation") parser.add_argument("-C", "--continous", action="store_true", dest="continuous", help="continuous computation") parser.add_argument("-s", "--stop", action="store_true", dest="stop", help="stop on register errors") parser.add_argument("-f", "--fdflag", action="store_false", dest="fdflag", default=True, help="de-activates under-over flow check for sfloats") parser.add_argument("-l", "--local", action="store_true", dest="local", default=True, help="True means run local computation") args = parser.parse_args() options = args if options.local: # Setup start, copied from compile.py and compilerLib.py args = [options.filename] local_path = os.path.join(options.filename, "local.py") party = options.party interface.mpc_type = interface.SPDZ _interface = [ t[1] for t in inspect.getmembers(interface, inspect.isclass) ] for op in _interface: VARS[op.__name__] = op param = -1 prog = Program(args, options, param) instructions.program = prog instructions_base.program = prog types.program = prog comparison.program = prog prog.DEBUG = options.debug VARS['program'] = prog comparison.set_variant(options) print 'Compiling file', prog.infile if instructions_base.Instruction.count != 0: print 'instructions count', instructions_base.Instruction.count instructions_base.Instruction.count = 0 prog.FIRST_PASS = False prog.reset_values() # make compiler modules directly accessible sys.path.insert(0, 'Compiler') # Setup end local_env = {} f = open(local_path, "r") local_program = f.read() temp = interface.mpc_type interface.mpc_type = interface.LOCAL exec(local_program, VARS, local_env) interface.mpc_type = temp f.close() cmd = "./Player.x {0} {1}".format(party, options.filename) + " -max 10,10,10" subprocess.call(cmd, shell=True)
def run_arithmetic(args, options, param=-1, merge_opens=True, \ reallocate=True, debug=False): from Compiler.program import Program from Compiler.config import * from Compiler.exceptions import * import instructions, instructions_base, types, comparison, library import interface from interface import ASTParser as ASTParser import inspect import copy interface.mpc_type = interface.SPDZ _interface = [t[1] for t in inspect.getmembers(interface, inspect.isclass)] for op in _interface: VARS[op.__name__] = op """ Compile a file and output a Program object. If merge_opens is set to True, will attempt to merge any parallelisable open instructions. """ prog = Program(args, options, param) instructions.program = prog instructions_base.program = prog types.program = prog comparison.program = prog prog.DEBUG = debug VARS['program'] = prog comparison.set_variant(options) print 'Compiling file', prog.infile if instructions_base.Instruction.count != 0: print 'instructions count', instructions_base.Instruction.count instructions_base.Instruction.count = 0 prog.FIRST_PASS = False prog.reset_values() # make compiler modules directly accessible sys.path.insert(0, 'Compiler') # create the tapes print 'Compiling file', prog.infile party = options.party a = ASTParser(prog.infile, party, debug=True) vectorized_calls, local_program = a.parse(options.split) if local_program: local_file = open(os.path.join(options.filename, "local.py"), "w") local_file.write(local_program) local_file.close() a.execute(VARS) # optimize the tapes for tape in prog.tapes: tape.optimize(options) if prog.main_thread_running: prog.update_req(prog.curr_tape) print 'Program requires:', repr(prog.req_num) print 'Memory size:', prog.allocated_mem print 'Program requires {0} rounds of communication in total.'.format( prog.rounds) print 'Program requires {0} invocations in total.'.format(prog.invocations) print 'Matmul calls: {0}'.format(vectorized_calls) for k in vectorized_calls.keys(): prog.req_num[k] = vectorized_calls[k] num_vectorized_triples, num_vectorized_bits = sub_vectorized_triples( vectorized_calls, prog.req_num) print "Due to vectorized triples, Reduced triple count by: {0}. Reduced bit count by: {1}.".format( num_vectorized_triples, num_vectorized_bits) #prog.req_num[('modp', 'triple')] -= num_vectorized_triples #prog.req_num[('modp', 'bit')] -= num_vectorized_bits # Don't want negative triples/bits assert (prog.req_num[('modp', 'triple')] >= num_vectorized_triples) assert (prog.req_num[('modp', 'bit')] >= num_vectorized_bits) # finalize the memory prog.finalize_memory() # Write file to output prog.write_bytes(options.outfile) return prog
def run(args, options): """ Compile a file and output a Program object. If options.merge_opens is set to True, will attempt to merge any parallelisable open instructions. """ prog = Program(args, options) VARS['program'] = prog if options.binary: VARS['sint'] = GC_types.sbitintvec.get_type(int(options.binary)) VARS['sfix'] = GC_types.sbitfixvec for i in 'cint', 'cfix', 'cgf2n', 'sintbit', 'sgf2n', 'sgf2nint', \ 'sgf2nuint', 'sgf2nuint32', 'sgf2nfloat', 'sfloat', 'cfloat', \ 'squant': del VARS[i] print('Compiling file', prog.infile) f = open(prog.infile, 'rb') changed = False if options.flow_optimization: output = [] if_stack = [] for line in open(prog.infile): if if_stack and not re.match(if_stack[-1][0], line): if_stack.pop() m = re.match( '(\s*)for +([a-zA-Z_]+) +in +range\(([0-9a-zA-Z_]+)\):', line) if m: output.append('%s@for_range_opt(%s)\n' % (m.group(1), m.group(3))) output.append('%sdef _(%s):\n' % (m.group(1), m.group(2))) changed = True continue m = re.match('(\s*)if(\W.*):', line) if m: if_stack.append((m.group(1), len(output))) output.append('%s@if_(%s)\n' % (m.group(1), m.group(2))) output.append('%sdef _():\n' % (m.group(1))) changed = True continue m = re.match('(\s*)elif\s+', line) if m: raise CompilerError('elif not supported') if if_stack: m = re.match('%selse:' % if_stack[-1][0], line) if m: start = if_stack[-1][1] ws = if_stack[-1][0] output[start] = re.sub(r'^%s@if_\(' % ws, r'%s@if_e(' % ws, output[start]) output.append('%s@else_\n' % ws) output.append('%sdef _():\n' % ws) continue output.append(line) if changed: infile = tempfile.NamedTemporaryFile('w+', delete=False) for line in output: infile.write(line) infile.seek(0) else: infile = open(prog.infile) else: infile = open(prog.infile) # make compiler modules directly accessible sys.path.insert(0, 'Compiler') # create the tapes exec(compile(infile.read(), infile.name, 'exec'), VARS) if changed and not options.debug: os.unlink(infile.name) prog.finalize() if prog.req_num: print('Program requires at most:') for x in prog.req_num.pretty(): print(x) if prog.verbose: print('Program requires:', repr(prog.req_num)) print('Cost:', 0 if prog.req_num is None else prog.req_num.cost()) print('Memory size:', dict(prog.allocated_mem)) return prog
#!/usr/bin/env python3 import sys, os sys.path.append(os.curdir) from Compiler.program import Program, defaults opts = defaults() opts.ring = 64 prog = Program(['direct_compilation'], opts) from Compiler.library import print_ln from Compiler.types import sint print_ln('%s', (sint(0) < sint(1)).reveal()) prog.finalize()