diff options
Diffstat (limited to 'chapters/introduction.adoc')
-rw-r--r-- | chapters/introduction.adoc | 64 |
1 files changed, 60 insertions, 4 deletions
diff --git a/chapters/introduction.adoc b/chapters/introduction.adoc index 33ebea1..72c0298 100644 --- a/chapters/introduction.adoc +++ b/chapters/introduction.adoc @@ -67,6 +67,62 @@ The following table summarizes the three profiles: |Main Training|TOSA-MT|Yes|Yes|Yes |=== +=== Compliance + +This section defines when a TOSA implementation is compliant to a given TOSA specification profile. +The term conformant will mean the same as compliant. + +==== Baseline Inference Profile + +The <<Operator Graphs>> section of this specification defines a TOSA graph and the behaviour defined for a TOSA graph. +This behaviour is captured in the pseudo-code function tosa_execute_graph(). +For a given input graph (with attributes) and input tensors there are three possible tosa_graph_result values after executing the graph: + +* tosa_unpredictable: The result of the graph on the given inputs cannot be relied upon. +* tosa_error: The graph does not meet the specification and is recognised as an illegal graph. +* tosa_valid: The result is defined and predictable and the list of output tensors defines the result. + +An implementation is compliant to the TOSA Baseline Inference Profile if it matches the above results as follows: + +* For tosa_unpredictable, the implementation can return whatever result it chooses (including error) +* For tosa_error, the implementation must return an error result (and there is no requirement on how much of the graph is executed, if any) +* For tosa_valid, the implementation must execute the entire graph without error and return the result defined by this specification. + +In terms of psuedo-code, if *graph* is a TOSA graph consisting of Baseline Inference Profile operators and *input_list* is a list of input tensors then the following test must pass. + +[source,c++] +---- +bool tosa_test_compliance(tosa_graph_t graph, tosa_list_t input_list) { + shape_list_t output_list_spec = tosa_allocate_list(tosa_output_shape(graph)); + shape_list_t output_list_test = tosa_allocate_list(tosa_output_shape(graph)); + tosa_graph_result = tosa_valid // result starts as valid + tosa_execute_graph(graph, input_list, output_list_spec); + if (tosa_graph_result == tosa_unpredictable) { + return true; // No requirement to match an unpredictable result + } + result_test = execute_implementation_under_test(graph, input_list, output_list_test); + if (tosa_graph_result == tosa_error) { + return result_test == tosa_error; // result must be an error + } + if (exact_tensor_match(output_list_spec, output_list_test)) { + // Predictable bit-exact value match required + return true; + } + return false; +} +---- + +==== Main Inference and Main Training Profile + +An implementation is compliant to the Main Inference or Main Training profiles if the following both hold for that respective profile: + +* For a graph returning tosa_error the implementation must also return an error +* For a graph returning tosa_valid the implementation must execute the entire graph without error +* For a graph returning tosa_valid and consisting only of integer operators the results must match exactly +* The implementation must report the maximum relative error on a set of standard graphs that contain floating point operators. These graphs will be provided as a future appendix to this specification. + +Note that for graphs containing floating point there is no strict precision requirement that must be met, but that the precision achieved must be reported. + === Operator Selection TOSA defines a set of primitive operators to which higher level operators can be lowered in a consistent way. To remain effective and efficient to implement the set of operators must be constrained to a reasonably small set of primitive operations out of which others can be constructed. The following principles govern the selection of operators within TOSA. @@ -197,9 +253,9 @@ The padding array represents the before and after pair for each dimension. [source,c++] ---- -REQUIRE((pad == NULL) || size(pad) == 2 * size(shape)); +ERROR_IF((pad != NULL) && size(pad) != 2 * size(shape)); out_t tensor_read<in_t>(in_t *address, dim_t shape, dim_t index, in_t zero_point=0, dim_t pad=NULL) { - REQUIRE(in_t == int8_t || zero_point == 0) + ERROR_IF(in_t != int8_t && zero_point != 0) unsigned offset = 0; for (i = 0; i < rank(shape); i++) { if (index[i] < 0) { @@ -242,10 +298,10 @@ The following function maps an index in the output tensor to an index in the inp [source,c++] ---- dim_t apply_broadcast(dim_t out_shape, dim_t in_shape, dim_t index) { - REQUIRE(rank(out_shape) == rank(in_shape)); + ERROR_IF(rank(out_shape) != rank(in_shape)); for (i = 0; i < rank(out_shape); i++) { if (out_shape[i] != in_shape[i]) { - REQUIRE(in_shape[i] == 1); + ERROR_IF(in_shape[i] != 1); index[i] = 0; } } |