Intermediate Representation

JSON IR Format

LightNet uses a JSON formatted intermediate representation (IR) to represent NN models, which is conforming to the following format:

{
    "ops": [
        {
            "name": STRING,
            "optype": STRING,
            "tensors_in": [
                {
                    "arg_name": STRING,
                    "name": STRING
                },
                ...
            ],
            "tensors_out": [
                {
                    "arg_name": STRING, 
                    "name": STRING
                },
                ...
            ],
            "params": [
                {
                    "arg_name": STRING,
                    "value": (ARRAY of) STRING or NUMBER or BOOL
                },
                ...
            ]
        },
        ...
    }
}

The IR format is very simple. It contains an array of operators ops, in which every operator is a JSON object. An operator should has the following fields:

  • name: A string name that is unique among all operators.
  • optype: A string of operator type that denotes the operation it performs.
  • tensors_in: The input tensors of the operator.
  • tensors_out: The output tensors of the operator.
  • params: The parameters of the operator.

See Operator for the corresponding C data structures of the above fields used by LightNet .

The elements of tensors_in, tensors_out and params all have a arg_name field. Think the operator as a C function, then arg_name is the argument name of that function. Thus, arg_name must be unique in the scope of the operator.

The name field in a tensor is the tensor's unique name among all tensors, which is used to look up the tensor in the tensor table. New tensors can only be defined in output tensors, and input tensors must have been defined by previous operators in their output tensors. See Tensor for details of the underlying data structures.

The value field in a parameter is its value, of the data type that the parameter requires. See Parameter for the possible data types and the underlying data structures used by parameters.

Example

The following code is an example of a simple IR composed of 3 operators: create1, slice1, and print1. create1 first creates a tensor tensor1 of shape 2 x 4, with float data [1, 2, 3, 4, 5, 6, 7, 8], then slice1 slices the tensor in its second axis (axis starts from 0), resulting to a tensor tensor2 of shape 2 x 3. Finally print1 prints tensor2 to stdout.

{
    "ops": [
        {
            "name": "create1",
            "optype": "create",
            "tensors_in": [
            ],
            "tensors_out": [
                {"arg_name": "dst", "name": "tensor1"}
            ],
            "params": [
                {"arg_name": "dtype", "value": "TL_FLOAT"},
                {"arg_name": "dims", "value": [2, 4]},
                {"arg_name": "data", "value": [1, 2, 3, 4, 5, 6, 7, 8]},
                {"arg_name": "ran", "value": [0, 0]},
                {"arg_name": "from_file", "value": false}
            ]
        },
        {
            "name": "slice1",
            "optype": "slice",
            "tensors_in": [
                {"arg_name": "src", "name": "tensor1"}
            ],
            "tensors_out": [
                {"arg_name": "dst", "name": "tensor2"}
            ],
            "params": [
                {"arg_name": "axis", "value": 1},
                {"arg_name": "start", "value": 1},
                {"arg_name": "len", "value": 3}
            ]
        },
        {
            "name": "print1",
            "optype": "print",
            "tensors_in": [
                {"arg_name": "src", "name": "tensor2"}
            ],
            "tensors_out": [
            ],
            "params": [
                {"arg_name": "msg", "value": "tensor2:"}
            ]
        }
    ]
}

If the above code is saved in example.json, executing the following command will give print1's message:

$ lightnet example.json
tensor2:
[[2.000 3.000 4.000]
 [6.000 7.000 8.000]]
info: run time: 0.000019s