Home | History | Annotate | Download | only in operation_signatures
      1 /*
      2  * Copyright (C) 2019 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "fuzzing/operation_signatures/OperationSignatureUtils.h"
     18 
     19 namespace android {
     20 namespace nn {
     21 namespace fuzzing_test {
     22 
     23 static void broadcastOpConstructor(Type dataType, uint32_t rank, RandomOperation* op) {
     24     // TODO: All inputs of the broadcast op have the same rank 4 for now.
     25     op->inputs[0]->dimensions.resize(rank);
     26     op->inputs[1]->dimensions.resize(rank);
     27     op->outputs[0]->dimensions.resize(rank);
     28     for (uint32_t i = 0; i < rank; i++) {
     29         if (getBernoulli(0.9f)) {
     30             op->inputs[0]->dimensions[i] = RandomVariableType::FREE;
     31         } else {
     32             op->inputs[0]->dimensions[i] = 1;
     33         }
     34         if (getBernoulli(0.9f)) {
     35             op->inputs[1]->dimensions[i] = op->inputs[0]->dimensions[i];
     36         } else {
     37             op->inputs[1]->dimensions[i] = 1;
     38         }
     39         op->outputs[0]->dimensions[i] =
     40                 max(op->inputs[0]->dimensions[i], op->inputs[1]->dimensions[i]);
     41     }
     42 
     43     // MUL requires output.scale > input0.scale * input1.scale.
     44     if (dataType == Type::TENSOR_QUANT8_ASYMM && op->opType == ANEURALNETWORKS_MUL) {
     45         float minScale = op->inputs[0]->scale * op->inputs[1]->scale;
     46         op->outputs[0]->scale = getUniform(minScale, minScale * 5);
     47     }
     48 
     49     // DIV and POW may produce Inf output values. We should not connect this output tensor to the
     50     // input of another operation.
     51     if (op->opType == ANEURALNETWORKS_DIV || op->opType == ANEURALNETWORKS_POW) {
     52         op->outputs[0]->doNotConnect = true;
     53     }
     54 }
     55 
     56 // For broadcast operations with fused activation.
     57 #define DEFINE_BROADCAST_WITH_ACT_SIGNATURE(op, ver, ...)                                        \
     58     DEFINE_OPERATION_SIGNATURE(op##_##ver){                                                      \
     59             .opType = ANEURALNETWORKS_##op,                                                      \
     60             .supportedDataTypes = {__VA_ARGS__},                                                 \
     61             .supportedRanks = {1, 2, 3, 4},                                                      \
     62             .version = HalVersion::ver,                                                          \
     63             .inputs = {INPUT_DEFAULT, INPUT_DEFAULT, PARAMETER_CHOICE(Type::INT32, 0, 1, 2, 3)}, \
     64             .outputs = {OUTPUT_DEFAULT},                                                         \
     65             .constructor = broadcastOpConstructor};
     66 
     67 // Arithmetic with activation.
     68 DEFINE_BROADCAST_WITH_ACT_SIGNATURE(ADD, V1_0, Type::TENSOR_FLOAT32, Type::TENSOR_QUANT8_ASYMM);
     69 DEFINE_BROADCAST_WITH_ACT_SIGNATURE(MUL, V1_0, Type::TENSOR_FLOAT32, Type::TENSOR_QUANT8_ASYMM);
     70 DEFINE_BROADCAST_WITH_ACT_SIGNATURE(SUB, V1_1, Type::TENSOR_FLOAT32);
     71 DEFINE_BROADCAST_WITH_ACT_SIGNATURE(DIV, V1_1, Type::TENSOR_FLOAT32);
     72 DEFINE_BROADCAST_WITH_ACT_SIGNATURE(ADD, V1_2, Type::TENSOR_FLOAT16);
     73 DEFINE_BROADCAST_WITH_ACT_SIGNATURE(MUL, V1_2, Type::TENSOR_FLOAT16);
     74 DEFINE_BROADCAST_WITH_ACT_SIGNATURE(SUB, V1_2, Type::TENSOR_FLOAT16, Type::TENSOR_QUANT8_ASYMM);
     75 DEFINE_BROADCAST_WITH_ACT_SIGNATURE(DIV, V1_2, Type::TENSOR_FLOAT16);
     76 
     77 // For broadcast ops with output of the same data type as inputs.
     78 #define DEFINE_BROADCAST_SIGNATURE(op, ver, ...)                                     \
     79     DEFINE_OPERATION_SIGNATURE(op##_##ver){.opType = ANEURALNETWORKS_##op,           \
     80                                            .supportedDataTypes = {__VA_ARGS__},      \
     81                                            .supportedRanks = {1, 2, 3, 4, 5},        \
     82                                            .version = HalVersion::ver,               \
     83                                            .inputs = {INPUT_DEFAULT, INPUT_DEFAULT}, \
     84                                            .outputs = {OUTPUT_DEFAULT},              \
     85                                            .constructor = broadcastOpConstructor};
     86 
     87 // Arithmetic without activation.
     88 DEFINE_BROADCAST_SIGNATURE(POW, V1_2, Type::TENSOR_FLOAT32, Type::TENSOR_FLOAT16);
     89 DEFINE_BROADCAST_SIGNATURE(PRELU, V1_2, Type::TENSOR_FLOAT32, Type::TENSOR_FLOAT16,
     90                            Type::TENSOR_QUANT8_ASYMM);
     91 DEFINE_BROADCAST_SIGNATURE(MAXIMUM, V1_2, Type::TENSOR_FLOAT32, Type::TENSOR_FLOAT16,
     92                            Type::TENSOR_QUANT8_ASYMM, Type::TENSOR_INT32);
     93 DEFINE_BROADCAST_SIGNATURE(MINIMUM, V1_2, Type::TENSOR_FLOAT32, Type::TENSOR_FLOAT16,
     94                            Type::TENSOR_QUANT8_ASYMM, Type::TENSOR_INT32);
     95 
     96 // Logical
     97 DEFINE_BROADCAST_SIGNATURE(LOGICAL_AND, V1_2, Type::TENSOR_BOOL8);
     98 DEFINE_BROADCAST_SIGNATURE(LOGICAL_OR, V1_2, Type::TENSOR_BOOL8);
     99 
    100 // Comparisons
    101 #define DEFINE_COMPARISON_SIGNATURE(op, ver, ...)                                         \
    102     DEFINE_OPERATION_SIGNATURE(op##_##ver){.opType = ANEURALNETWORKS_##op,                \
    103                                            .supportedDataTypes = {__VA_ARGS__},           \
    104                                            .supportedRanks = {1, 2, 3, 4},                \
    105                                            .version = HalVersion::ver,                    \
    106                                            .inputs = {INPUT_DEFAULT, INPUT_DEFAULT},      \
    107                                            .outputs = {OUTPUT_TYPED(Type::TENSOR_BOOL8)}, \
    108                                            .constructor = broadcastOpConstructor};
    109 
    110 DEFINE_COMPARISON_SIGNATURE(EQUAL, V1_2, Type::TENSOR_FLOAT32, Type::TENSOR_FLOAT16,
    111                             Type::TENSOR_INT32, Type::TENSOR_QUANT8_ASYMM, Type::TENSOR_BOOL8);
    112 DEFINE_COMPARISON_SIGNATURE(GREATER, V1_2, Type::TENSOR_FLOAT32, Type::TENSOR_FLOAT16,
    113                             Type::TENSOR_INT32, Type::TENSOR_QUANT8_ASYMM);
    114 DEFINE_COMPARISON_SIGNATURE(GREATER_EQUAL, V1_2, Type::TENSOR_FLOAT32, Type::TENSOR_FLOAT16,
    115                             Type::TENSOR_INT32, Type::TENSOR_QUANT8_ASYMM);
    116 DEFINE_COMPARISON_SIGNATURE(LESS, V1_2, Type::TENSOR_FLOAT32, Type::TENSOR_FLOAT16,
    117                             Type::TENSOR_INT32, Type::TENSOR_QUANT8_ASYMM);
    118 DEFINE_COMPARISON_SIGNATURE(LESS_EQUAL, V1_2, Type::TENSOR_FLOAT32, Type::TENSOR_FLOAT16,
    119                             Type::TENSOR_INT32, Type::TENSOR_QUANT8_ASYMM);
    120 DEFINE_COMPARISON_SIGNATURE(NOT_EQUAL, V1_2, Type::TENSOR_FLOAT32, Type::TENSOR_FLOAT16,
    121                             Type::TENSOR_INT32, Type::TENSOR_QUANT8_ASYMM, Type::TENSOR_BOOL8);
    122 
    123 }  // namespace fuzzing_test
    124 }  // namespace nn
    125 }  // namespace android
    126