Полностью подключенный слой TensorFlow Lite Micro на новой аппаратной цели падает - PullRequest
0 голосов
/ 27 июня 2019

В настоящее время я добавляю поддержку новой аппаратной цели (процессоры LEON 3 на базе Sparc V8) в инфраструктуру TensorFlow Lite Micro.Когда я собираю и запускаю встроенные тесты для этой цели, они все проходят.Однако я не могу заставить ни один из включенных примеров выполнить новую цель без сбоев во время вывода.

Я сделал действительно простую игрушечную модель, которая представляет собой полностью связанный слой 20x10, встроенный в TensorFlow Lite Micro работает нормально, но когда я собираю и запускаю его для LEON 3, он вылетает с доступом к данным.исключение »на этапе вывода.Мне удалось отследить сбой до вызова для оценки на полностью подключенном слое, который является единственным оператором в TensorFlow Lite Model.Я сделал это, добавив отладочные отпечатки в метод MicroInterpreter :: Invoke (), чтобы определить, где в этом методе произошел сбой.

Вот исходный код main.cc для моего игрушечного примера.Этот код сборки и прекрасно выполняется для собственной цели linux_x86_64.

#include <stdio.h>
#include "tensorflow/lite/experimental/micro/examples/toy_model/model/tiny_model_data.h"
#include "tensorflow/lite/experimental/micro/kernels/all_ops_resolver.h"
#include "tensorflow/lite/experimental/micro/micro_error_reporter.h"
#include "tensorflow/lite/experimental/micro/micro_interpreter.h"
#include "tensorflow/lite/schema/schema_generated.h"
#include "tensorflow/lite/version.h"


int main(int argc, char* argv[]) {
  // Set up logging.
  tflite::MicroErrorReporter micro_error_reporter;
  tflite::ErrorReporter* error_reporter = &micro_error_reporter;

  printf("Parsing model FlatBuffer.\n");

  // Map the model into a usable data structure. This doesn't involve any
  // copying or parsing, it's a very lightweight operation.
  const tflite::Model* model =
      ::tflite::GetModel(tiny_tflite);
  if (model->version() != TFLITE_SCHEMA_VERSION) {
    error_reporter->Report(
        "Model provided is schema version %d not equal "
        "to supported version %d.\n",
        model->version(), TFLITE_SCHEMA_VERSION);
    return 1;
  }

  printf("Model parsed.\n");

  // This pulls in all the operation implementations we need.
  printf("Pull in operation implementations.");
  tflite::ops::micro::AllOpsResolver resolver;
  printf("Done.\n");

  // Create an area of memory to use for input, output, and intermediate arrays.
  // The size of this will depend on the model you're using, and may need to be
  // determined by experimentation.
  printf("Allocate memory buffer.\n");
  const int tensor_arena_size = 200 * 1024;
  uint8_t tensor_arena[tensor_arena_size];
  tflite::SimpleTensorAllocator tensor_allocator(tensor_arena,
                                                 tensor_arena_size);
  printf("Done.\n");

  // Build an interpreter to run the model with.
  printf("Build interpreter.\n");
  tflite::MicroInterpreter interpreter(model, resolver, &tensor_allocator,
                                       error_reporter);
  printf("Done.\n");

  printf("Setting input data.\n");
  TfLiteTensor* model_input = interpreter.input(0);
  for (int d=0; d<20; ++d)
    model_input->data.f[d] = d / 20.0;
  printf("Done.\n");

  // perform inference
  printf("Perform inference.\n");
  TfLiteStatus invoke_status = interpreter.Invoke();
    if (invoke_status != kTfLiteOk) {
      printf("Invoke failed.\n");
      return 1;
    }
  printf("Done.\n");

  TfLiteTensor* model_output = interpreter.output(0);

  printf("Output tensor values:\n");
  for (int d=0; d<10; ++d)
    printf("[%d] %f\n", d, model_output->data.f[d]);

  return 0;
}

Вот вывод при успешном выполнении собственной сборки:

Parsing model FlatBuffer.
Model parsed.
Pull in operation implementations.Done.
Allocate memory buffer.
Done.
Build interpreter.
Done.
Details of input tensors 0 :
Rank 2, type [Float32], shape [1, 20]
Setting input data.
Done.
Perform inference.
Entered Invoke()
init was okay.
get opcodes.
Starting operator [0]
Starting operator [0] 1
Starting operator [0] 2
Starting operator [0] 3
Starting operator [0] 4
Starting operator [0] 5
Starting operator [0] 6
Starting operator [0] 7
Starting operator [0] 8
Starting operator [0] 9
Starting operator [0] 10
Starting operator [0] 11
Starting operator [0] 12
Node FULLY_CONNECTED (number 0)
Starting operator [0] 13
Starting operator [0] 14
Done.
Details of output tensors 0 :
Rank 2, type [Float32], shape [1, 10]
Output tensor values:
[0] -0.085346
[1] -0.071581
[2] 0.195880
[3] -0.198830
[4] -0.255614
[5] -0.350692
[6] 0.053310
[7] -0.011272
[8] -0.107219
[9] 0.037424

И вывод при выполнении сборки LEON, которыйне удается.

tsim> run
starting at 0x40000000
Parsing model FlatBuffer.
Model parsed.
Pull in operation implementations.Done.
Allocate memory buffer.
Done.
Build interpreter.
Done.
Details of input tensors 0 :
Rank 2, type [Float32], shape [1, 20]
Setting input data.
Done.
Perform inference.
Entered Invoke()
init was okay.
get opcodes.
Starting operator [0]
Starting operator [0] 1
Starting operator [0] 2
Starting operator [0] 3
Starting operator [0] 4
Starting operator [0] 5
Starting operator [0] 6
Starting operator [0] 7
Starting operator [0] 8
Starting operator [0] 9
Starting operator [0] 10
Starting operator [0] 11
Starting operator [0] 12
Node FULLY_CONNECTED (number 0)

IU in error mode (tt=0x80, trap instruction)
(In trap table for tt=0x09, data access exception)
   162855  40000090  91d02000   ta  0x0

Интересно, что когда я запускаю нативный код через valgrind с подробным выводом (-v), я получаю два предупреждения REDIR, приведенные ниже, именно в той точке, где происходит сбой версии LEON3.

Starting operator [0]
Starting operator [0] 1
Starting operator [0] 2
Starting operator [0] 3
Starting operator [0] 4
Starting operator [0] 5
Starting operator [0] 6
Starting operator [0] 7
Starting operator [0] 8
Starting operator [0] 9
Starting operator [0] 10
Starting operator [0] 11
Starting operator [0] 12
Node FULLY_CONNECTED (number 0)
--4540-- REDIR: 0x55593f0 (libc.so.6:memcpy@@GLIBC_2.14) redirected to 0x4a286f0 (_vgnU_ifunc_wrapper)
--4540-- REDIR: 0x5612ea0 (libc.so.6:__memcpy_avx_unaligned) redirected to 0x4c324a0 (memcpy@@GLIBC_2.14)
Starting operator [0] 13
Starting operator [0] 14
Done.

Если кто-либо из TensorFlow Lite Micro Team или пользователей имеет какое-либо представление о том, что является причиной этого, или какие-либо возможные недостатки в реализации цели LIBC, тогда я действительно буду признателен за любые идеи.

Спасибо.

...