Add Conv1x1 microbenchmark A simple example of deploying the tosa.conv2d 1x1 model. The input is set to zero so the output is just the bias (input = conv2d zero_point). Change-Id: Ied4f02a387aff5c180af938a06602b5103c50844
diff --git a/samples/microbenchmarks/CMakeLists.txt b/samples/microbenchmarks/CMakeLists.txt new file mode 100644 index 0000000..df7230b --- /dev/null +++ b/samples/microbenchmarks/CMakeLists.txt
@@ -0,0 +1,34 @@ +# ------------------------------------------------------------------------------- +# Build the mlir bytecode modules with iree-compile. Note the last two flags +# are for RVV support. +# https://github.com/llvm/llvm-project/blob/0eeab8b/llvm/lib/Target/RISCV/RISCVSubtarget.cpp#L30-L51 +# ------------------------------------------------------------------------------- + +springbok_c_module( + NAME + conv1x1_test + SRC + "conv1x1_test.mlir" + FLAGS + "-iree-input-type=tosa" + "-riscv-v-vector-bits-min=512" + "-riscv-v-fixed-length-vector-lmul-max=8" + PUBLIC +) + +springbok_test( + NAME + conv1x1_test_emitc_static + SRCS + "conv1x1_test.c" + DEPS + ::conv1x1_test_c + ::conv1x1_test_emitc + model_util::util + LINKOPTS + "LINKER:--defsym=__stack_size__=64k" + COPTS + "-DBUILD_EMITC_STATIC" + TESTFILES + "conv1x1_test.run" +)
diff --git a/samples/microbenchmarks/conv1x1_test.c b/samples/microbenchmarks/conv1x1_test.c new file mode 100644 index 0000000..68932bc --- /dev/null +++ b/samples/microbenchmarks/conv1x1_test.c
@@ -0,0 +1,65 @@ +// conv 1x1 tosa op test. + +#include "iree/base/api.h" +#include "iree/hal/api.h" +#include "model_util/util.h" +#include "samples/microbenchmarks/conv1x1_test_c.h" +#include "samples/microbenchmarks/conv1x1_test_emitc.h" + +const MlModel kModel = { + .num_input = 1, + .num_input_dim = {4}, + .input_shape = {{1, 112, 112, 8}}, + .input_length = {112 * 112 * 8}, + .input_size_bytes = {sizeof(int8_t)}, + .num_output = 1, + .output_length = {112 * 112 * 16}, + .output_size_bytes = sizeof(int8_t), + .hal_element_type = IREE_HAL_ELEMENT_TYPE_SINT_8, + .entry_func = "module.main", + .model_name = "conv1x1_quant", +}; + +iree_status_t create_module(iree_vm_instance_t *instance, + iree_vm_module_t **module) { + return module_create(instance, iree_allocator_system(), module); +} + +iree_hal_executable_library_query_fn_t library_query(void) { + return conv1x1_test_linked_llvm_cpu_library_query; +} + +iree_status_t load_input_data(const MlModel *model, void **buffer, + iree_const_byte_span_t **byte_span) { + iree_status_t result = alloc_input_buffer(model, buffer); + // Populate initial value to effectively 0 w.r.t conv1x1, so the output is the + // same as the bias. + memset((int8_t *)buffer[0], -128, + model->input_length[0] * model->input_size_bytes[0]); + byte_span[0] = malloc(sizeof(iree_const_byte_span_t)); + *byte_span[0] = iree_make_const_byte_span( + buffer[0], model->input_size_bytes[0] * model->input_length[0]); + return result; +} + +iree_status_t process_output(const MlModel *model, + iree_hal_buffer_mapping_t *buffers, + MlOutput *output) { + iree_status_t result = iree_ok_status(); + // Output is ((bias + input_zp) * multiplier) >> shift + output_zp after + // rescale. + const int8_t kExpectedOutput[] = {-128, -128, -125, -128, -128, 127, + -107, -128, -128, -128, -128, -105, + 74, 127, -128, 69}; + for (int i = 0; i < model->output_length[0] / sizeof(kExpectedOutput); ++i) { + for (int j = 0; j < sizeof(kExpectedOutput); ++j) { + if ((((const int8_t *)buffers[0] + .contents.data)[i * sizeof(kExpectedOutput) + j]) != + kExpectedOutput[j]) { + result = iree_make_status(IREE_STATUS_UNKNOWN, "result mismatches"); + break; + } + } + } + return result; +}
diff --git a/samples/microbenchmarks/conv1x1_test.mlir b/samples/microbenchmarks/conv1x1_test.mlir new file mode 100644 index 0000000..587f24a --- /dev/null +++ b/samples/microbenchmarks/conv1x1_test.mlir
@@ -0,0 +1,9 @@ +module { + func.func @main(%arg0: tensor<1x112x112x8xi8>) -> tensor<1x112x112x16xi8> { + %0 = "tosa.const"() {value = dense<[-918, -4433, 87, -234, -21393, 7738, 529, -8835, -16817, -375, -199, 572, 5082, 15569, -186, 4955]> : tensor<16xi32>} : () -> tensor<16xi32> + %1 = "tosa.const"() {value = dense<"0xE2E2E2E2E2EBF6E206E2E2E8EBE6DEE2E0E2E2FDDCE7E1E2E2E2E2FDDFE6E0E3EBE2E2DCEFAC213DE2E2E2E3E2D3C9E4E2E2E2E2E3E1E1FA3EE2E2E9E9E5E3E47FE2E2E4EDE2E2E3E0E2E2E4DFE9DCFEE3E2E2E2E2E2E2E2F9E2E2E6EBEADCE4E2E2E2CEE5E1E0E181E2E2D9D3DEE1DDE2E2E2E2E2E2E2E2C5E2E2E2DBE1E3E1"> : tensor<16x1x1x8xi8>} : () -> tensor<16x1x1x8xi8> + %2 = "tosa.conv2d"(%arg0, %1, %0) {dilation = [1, 1], pad = [0, 0, 0, 0], quantization_info = #tosa.conv_quant<input_zp = -128, weight_zp = -30>, stride = [1, 1]} : (tensor<1x112x112x8xi8>, tensor<16x1x1x8xi8>, tensor<16xi32>) -> tensor<1x112x112x16xi32> + %3 = "tosa.rescale"(%2) {double_round = true, input_zp = 0 : i32, multiplier = [1364139008 : i32], output_zp = -128 : i32, per_channel = false, scale32 = true, shift = [35 : i32]} : (tensor<1x112x112x16xi32>) -> tensor<1x112x112x16xi8> + return %3 : tensor<1x112x112x16xi8> + } +}
diff --git a/samples/microbenchmarks/conv1x1_test.run b/samples/microbenchmarks/conv1x1_test.run new file mode 100644 index 0000000..2aa9a92 --- /dev/null +++ b/samples/microbenchmarks/conv1x1_test.run
@@ -0,0 +1 @@ +// RUN: ${TEST_RUNNER_CMD} %S/conv1x1_test_emitc_static