def main(): logging.basicConfig(filename='test_loops.log', filemode='w') logger = logging.getLogger('test_loops') logger.setLevel(logging.INFO) logging.getLogger('loops.compose').setLevel(logging.INFO) parser = argparse.ArgumentParser() parser.add_argument('-t', '--tests', action='store_true', help='run the test suite') parser.add_argument('-c', '--compose', action='append', type=argparse.FileType('r'), default=[], nargs='*', metavar='file', help='count how many ways this file can be composed into a single opt') parser.add_argument('-l', '--loop', action='append', type=argparse.FileType('r'), default=[], nargs='*', metavar='file', help='check whether each file describes a cycle') parser.add_argument('-v', '--verify', action='store_true', help='if present, verify all composed optimizations') parser.add_argument('--log', action='append', nargs=2, metavar=('logger', 'level'), help='set the logging threshold for a logging subtree') args = parser.parse_args() if args.log: for tree,level in args.log: level = level.upper() if level not in ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']: sys.stderr.write('{} is not a valid logging level\n'.format(level)) sys.stderr.write('Use: DEBUG, INFO, WARNING, ERROR, CRITICAL\n') exit(-1) logging.getLogger(tree).setLevel(getattr(logging, level)) logger.info('logging %s at %s', tree, level) for f in itertools.chain.from_iterable(args.compose): opts = loops.parse_transforms(f.read()) comps = test_composition(opts, f.name, verify=args.verify, quiet=False) print '{}: got {} composition{}'.format(f.name, comps, '' if comps == 1 else 's') for f in itertools.chain.from_iterable(args.loop): opts = loops.parse_transforms(f.read()) loop = test_loop(opts, f.name, verify=args.verify, quiet=False) print '{}: {}loop'.format(f.name, '' if loop else 'no ') if args.tests or not (args.compose or args.loop): if not run_tests(verify=args.verify): exit(1)
def search_process(suite, limit, sequence_queue, result_queue, status_queue, log_config): logging.config.dictConfig(log_config) log = logger.getChild('search_process') log.info('Worker thread started, limit %s', limit) opts = loops.parse_transforms(open(suite).read()) log.debug('%s optimizations', len(opts)) info = [0,0,0,0] def count_error(e,o1,o2): info[ERRORS] += 1 while info[COUNT] < limit: s = sequence_queue.get() if s is None: log.info('Worker exiting %s', info) status_queue.put(info) return log.debug('Checking sequence %s', s) os = tuple(opts[i] for i in s) for o in loops.all_compositions(os): if info[COUNT] >= limit: break o_src = count_src(o) for oo in loops.all_bin_compositions(o, o, count_error): if info[COUNT] >= limit: break if info[COUNT] % 1000 == 0: log.info('Tested %s SatChecks %s Loops %s Errors %s', *info) info[COUNT] += 1 oo_src = count_src(oo) if o_src < oo_src: continue info[SAT_CHECKS] += 1 if not loops.satisfiable(oo): continue info[CYCLES] += 1 # TODO: put found loops into a queue result = 'Loop: {}\n{}\n\n{}'.format(o.name, '\n\n'.join(str(op) for op in os), o) result_queue.put(result) log.info(result) log.info('Worker exiting %s', info) status_queue.put(info)
def main(): logging.basicConfig(filename='find-loops.log', filemode='w') parser = argparse.ArgumentParser() parser.add_argument('length', type=int, help='Length of cycles to search for') parser.add_argument('file', type=argparse.FileType('r'), help='optimization suite to analyze') args = parser.parse_args() if args.length < 1: sys.stderr.write('cycle length must be positive\n') exit(1) sys.stderr.write('Reading ' + args.file.name + '\n') opts = loops.parse_transforms(args.file.read()) sys.stderr.write('{} optimizations'.format(len(opts))) count = 0 sat_checks = 0 cycles = 0 errors = [0] def count_error(e,o1,o2): errors[0] += 1 for o,_,os in search(opts, args.length): o_src = count_src(o) for oo in loops.all_bin_compositions(o,o,count_error): sys.stderr.write(status.format(count, sat_checks, cycles)) count += 1 oo_src = count_src(oo) if o_src < oo_src: continue sat_checks += 1 if not loops.satisfiable(oo): continue cycles += 1 print '\n-----\nLoop: ', o.name for opt in os: opt.dump() print o.dump() sys.stderr.write(status.format(count, sat_checks, cycles)) sys.stderr.write('\n') print print 'final count', count print 'loops', cycles print 'sat_checks', sat_checks print 'errors', errors[0]
def search_process(suite, length, prefix_queue, result_queue, status_queue, log_config): logging.config.dictConfig(log_config) log = logger.getChild("search_process") log.info("Worker thread started") opts = loops.parse_transforms(open(suite).read()) log.debug("%s optimizations", len(opts)) info = [0] * INFO_FLDS def count_error(e, o1, o2): info[ERRORS] += 1 while info[COMPS] < MAX_TESTS: p = prefix_queue.get() if p is None: log.info("Worker exiting %s", info) status_queue.put(info) prefix_queue.task_done() # make sure this happens after putting the info return log.info("Checking prefix %s", p) for o, os in search_after_prefix(opts, length, p, count_error): o_src = count_src(o) info[COMPS] += 1 if info[COMPS] % 1000 == 0: log.info("Seqs %s Comps %s SelfComps %s SatChecks %s Loops %s Errors %s", *info) for oo in loops.all_bin_compositions(o, o, count_error): info[SELF_COMPS] += 1 oo_src = count_src(oo) if o_src < oo_src: continue info[SAT_CHECKS] += 1 if not loops.satisfiable(oo): continue info[CYCLES] += 1 # TODO: put found loops into a queue result = "Loop: {}\n{}\n\n{}".format(o.name, "\n\n".join(str(op) for op in os), o) result_queue.put(result) log.info(result) info[SEQS] += prefix_size(p, length, len(opts)) prefix_queue.task_done() log.info("Worker exiting %s", info) status_queue.put(info)
def count_opts(suite): opts = loops.parse_transforms(open(suite).read()) return len(opts)
def search_process(suite, length, limit, prefix_queue, result_queue, status_queue, log_config): logging.config.dictConfig(log_config) log = logger.getChild('search_process') log.info('Worker thread started') opts = loops.parse_transforms(open(suite).read()) log.debug('%s optimizations', len(opts)) info = [0] * INFO_FLDS def count_error(e,o1,o2): info[ERRORS] += 1 complete = True while info[COMPS] < limit: p = prefix_queue.get() if p is None: log.info('Worker exiting %s', info) status_queue.put(info) prefix_queue.task_done() # make sure this happens after putting the info return log.info('Checking prefix %s; %s remaining', p, limit-info[COMPS]) counters = [0] * length for o,os in search_after_prefix(opts, length, p, counters, count_error): o_src = count_src(o) info[COMPS] += 1 if info[COMPS] % 1000 == 0: log.info('Paths %s Comps %s Selfcomps %s SatChecks %s Loops %s Errors %s', *info) for oo in loops.all_bin_compositions(o, o, count_error): # TODO: can this just be compose? info[SELFCOMPS] += 1 oo_src = count_src(oo) if o_src < oo_src: continue info[SAT_CHECKS] += 1 if not loops.satisfiable(oo): continue info[CYCLES] += 1 # TODO: put found loops into a queue result = 'Loop: {}\n{}\n\n{}'.format(o.name, '\n\n'.join(str(op) for op in os), o) result_queue.put(result) log.info(result) if info[COMPS] >= limit: complete = False break if complete: psize = prefix_size(p, length, len(opts)) log.debug('Prefix %s size %s counters %s', p, psize, counters) info[SEQS] += psize else: psize = partial_prefix_size(p, counters, len(opts)) info[SEQS] += psize log.debug('Prefix %s size %s Info %s Counters %s', p, psize, info, counters) prefix_queue.task_done() log.info('Worker exiting %s', info) status_queue.put(info)
def run_tests(verify=False): logger = logging.getLogger('test_loops') complete = 0 failed = 0 errors = [0] test_names = filter(lambda f: not f.startswith('unknown'), os.listdir('looptests')) tests = len(test_names) sys.stderr.write(str(tests) + ' tests\n') label = re.compile(r'^; expect (\d+) (comp|loop)') def count_error(*args): errors[0] += 1 def statusmsg(): sys.stderr.write( '\r{}% complete, {} failed, {} errors'.format( complete*100/tests, failed, errors[0])) for f in test_names: logger.info('reading looptests/%s', f) statusmsg() complete += 1 text = open('looptests/' + f).read() expects = label.match(text) if not expects: logger.warning('%s: no expectations', f) errors += 1 continue expected = int(expects.group(1)) expecting = expects.group(2) opts = loops.parse_transforms(text) try: if expecting == 'comp': comps = test_composition(opts, f, verify=verify, on_error=count_error) if comps != expected: logger.warning('%s: Got %r comps, expected %r', f, comps, expected) failed += 1 continue if expecting == 'loop': got = test_loop(opts, f, verify=verify, on_error=count_error) if got and not expected: logger.warning('%s: Unexpected loop', f) failed += 1 elif not got and expected: logger.warning('%s: Expected loop', f) failed += 1 except Exception as e: logger.exception('Got %r while testing %s', e, f) errors[0] += 1 statusmsg() sys.stderr.write('\n') return not failed and not errors[0]