#!/usr/bin/env python from __future__ import absolute_import from __future__ import division from __future__ import print_function from __future__ import unicode_literals import string import argparse import numpy as np from caffe2.python.model_helper import ModelHelper from caffe2.python.predictor import mobile_exporter from caffe2.python import core, workspace, brew, utils def parse_kwarg(kwarg_str): key, value = map(string.strip, kwarg_str.split("=", 1)) try: value = int(value) except ValueError: try: value = float(value) except ValueError: pass return key, value def main(args): # User defined keyword arguments kwargs = {"order": "NCHW"} kwargs.update(dict(args.kwargs)) model = ModelHelper(name=args.benchmark_name) op_type = args.operator # assumes a brew type op name input_name = args.input_name output_name = args.output_name iters = int(args.iters) for i in range(iters): input_blob_name = input_name + (str(i) if i > 0 and args.chain else '') output_blob_name = output_name + str(i + 1) add_op = getattr(brew, op_type) add_op(model, input_blob_name, output_blob_name, **kwargs) if args.chain: input_name, output_name = output_name, input_name workspace.RunNetOnce(model.param_init_net) extra_init_net_ops = [] def make_blob_on_context(blob_name, blob_data, context): if context.upper() != "CPU": blob_name_modified = "{}_CPU".format(blob_name) else: # CPU case is simple blob_name_modified = blob_name fill_op = core.CreateOperator( "GivenTensorFill", [], [blob_name_modified], arg=[ utils.MakeArgument("shape", blob_data.shape), utils.MakeArgument("values", blob_data) ] ) extra_init_net_ops.append(fill_op) # We need to create CPU blobs and add some copy operations in # the init_net if context.upper() == "OPENGL": copy_op = core.CreateOperator("CopyToOpenGL", [blob_name_modified], [blob_name]) extra_init_net_ops.append(copy_op) for unparsed_blob in args.blob: name, unparsed_dims = unparsed_blob.split('=') dims = [int(d) for d in unparsed_dims.split(',')] np_input = np.random.rand(*dims).astype(np.float32) make_blob_on_context(name, np_input, args.context) init_net, predict_net = mobile_exporter.Export( workspace, model.net, model.params ) init_net.op.extend(extra_init_net_ops) # Handle manual rewrite if args.context.upper() == "OPENGL": old_ops = [op for op in predict_net.op] del predict_net.op[:] for op in old_ops: op.type = 'OpenGL{}'.format(op.type) predict_net.op.extend(old_ops) if args.debug: print("init_net:") for op in init_net.op: print(" ", op.type, op.input, "-->", op.output) print("predict_net:") for op in predict_net.op: print(" ", op.type, op.input, "-->", op.output) with open(args.predict_net, 'wb') as f: f.write(predict_net.SerializeToString()) with open(args.init_net, 'wb') as f: f.write(init_net.SerializeToString()) if __name__ == "__main__": parser = argparse.ArgumentParser( description="Utilitity to generate Caffe2 benchmark models.") parser.add_argument("operator", help="Caffe2 operator to benchmark.") parser.add_argument("-b", "--blob", help="Instantiate a blob --blob name=dim1,dim2,dim3", action='append') parser.add_argument("--context", help="Context to run on.", default="CPU") parser.add_argument("--kwargs", help="kwargs to pass to operator.", nargs="*", type=parse_kwarg, default=[]) parser.add_argument("--init_net", help="Output initialization net.", default="init_net.pb") parser.add_argument("--predict_net", help="Output prediction net.", default="predict_net.pb") parser.add_argument("--benchmark_name", help="Name of the benchmark network", default="benchmark") parser.add_argument("--input_name", help="Name of the input blob.", default="data") parser.add_argument("--output_name", help="Name of the output blob.", default="output") parser.add_argument("--iters", help="Number of iterations to run the operator.", default="1") parser.add_argument("-d", "--debug", help="Print debug information.", action='store_true') parser.add_argument("-c", "--chain", help="Chain ops together (create data dependencies)", action='store_true') args = parser.parse_args() main(args)