Beispiel #1
0
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
Beispiel #2
0
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
Beispiel #3
0
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
Beispiel #4
0
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
Beispiel #5
0
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)
Beispiel #6
0
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
Beispiel #7
0
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
Beispiel #8
0
#!/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()