TF Lite C API вылетает на второй итерации - PullRequest
0 голосов
/ 07 мая 2020

Я пытаюсь использовать C API TF Lite для циклического выполнения логического вывода, например, я настраиваю интерпретатор и загружаю ему входные данные каждую секунду или около того, чтобы получать прогнозы.

Для этой цели, Я построил libtensorflowlite_c.so с помощью bazel. Как описано в здесь , я пытаюсь сделать вывод, подобный этому, но внутри for l oop для имитации выполнения cycli c:

#include "tensorflow/lite/c/c_api.h"
#include <stdio.h>
#include <stdlib.h>


int main (int argc, char* argv[]) {

   for(int i = 0; i < 3; i++)
    {
        printf("Iteration: %d\n", i);

        float input[49] = { 0.0 };
        TfLiteModel* model = TfLiteModelCreateFromFile("model.tflite");
        TfLiteInterpreterOptions* options = TfLiteInterpreterOptionsCreate();
        TfLiteInterpreterOptionsSetNumThreads(options, 2);
        TfLiteInterpreter* interpreter = TfLiteInterpreterCreate(model, options);
        TfLiteInterpreterAllocateTensors(interpreter);

        TfLiteTensor* input_tensor = TfLiteInterpreterGetInputTensor(interpreter, 0);
        TfLiteTensorCopyFromBuffer(input_tensor, input, 49 * sizeof(float));

        TfLiteInterpreterInvoke(interpreter);

        const TfLiteTensor* output_tensor = TfLiteInterpreterGetOutputTensor(interpreter, 14);

        float output[49];
        TfLiteTensorCopyToBuffer(output_tensor, output, 49 * sizeof(float));

        printf("Output: \n\n");
        for (int j = 0; j < 49; j++) {
            printf("%d: %f\n", j, output[j]);
        }

        TfLiteInterpreterDelete(interpreter);
        TfLiteInterpreterOptionsDelete(options);
        TfLiteModelDelete(model);
    }
    return 0;
}

Первая итерация работает нормально и что-то возвращает. Но на второй итерации я получаю SegFault при вызове TfLiteTensorCopyToBuffer(output_tensor, output, 49 * sizeof(float));. Причина в том, что предыдущая функция TfLiteInterpreterGetOutputTensor возвращает нулевой указатель.

Я ожидал запустить это несколько раз без каких-либо проблем, так как я уничтожаю все старые экземпляры переменных в конце for-l oop и, таким образом, каждый раз запускать интерпретатор fre sh. Очевидно, что это не так.

Может кто-нибудь дать какие-нибудь указания по этому поводу? Кроме того, я знаю, что мне, вероятно, не нужно создавать интерпретатор на каждой итерации, но я хотел убедиться, что все создается заново, когда я начинаю заново.

РЕДАКТИРОВАТЬ:

Я попытался переписать код, чтобы исключить ненужные части из фактического l oop:

#include "tensorflow/lite/c/c_api.h"
#include <stdio.h>
#include <stdlib.h>


int main (int argc, char* argv[]) {

    float input[49] = {0.0};
    float output[49] = {[0 ... 48] = 2.5};

    TfLiteModel* model = TfLiteModelCreateFromFile("VariationalAutoencoder_440.tflite");
    TfLiteInterpreterOptions* options = TfLiteInterpreterOptionsCreate();
    TfLiteInterpreterOptionsSetNumThreads(options, 2);
    TfLiteInterpreter* interpreter = TfLiteInterpreterCreate(model, options);
    TfLiteInterpreterAllocateTensors(interpreter);
    TfLiteTensor* input_tensor = TfLiteInterpreterGetInputTensor(interpreter, 0);
    const TfLiteTensor* output_tensor = TfLiteInterpreterGetOutputTensor(interpreter, 14);

    for(int i = 0; i < 3; i++)
    {
        printf("\nIteration: %d\n", i);
        TfLiteTensorCopyFromBuffer(input_tensor, input, 49 * sizeof(float));
        TfLiteInterpreterInvoke(interpreter);
        TfLiteTensorCopyToBuffer(output_tensor, output, 49 * sizeof(float));

        printf("Output: \n");
        for (int j = 0; j < 49; j++)
        {
            printf("%02d: %f\n", j, output[j]);
        }
    }

    TfLiteInterpreterDelete(interpreter);
    TfLiteInterpreterOptionsDelete(options);
    TfLiteModelDelete(model);

    return 0;
}

Ответы [ 2 ]

1 голос
/ 07 мая 2020

Ваш код работает нормально, если TfLiteInterpreterGetOutputTensor использовать индекс ниже TfLiteInterpreterGetOutputTensorCount.

Может быть, тензорный индекс 14 должен быть 13, но это зависит от вашей модели.

Добавление проверки например:

    int count = TfLiteInterpreterGetOutputTensorCount(interpreter);
    printf("output tensor count:%d\n", count);
    if (count > 14) {
       const TfLiteTensor* output_tensor = TfLiteInterpreterGetOutputTensor(interpreter, 14);

       float output[49];
       TfLiteTensorCopyToBuffer(output_tensor, output, 49 * sizeof(float));

       printf("Output: \n\n");
       for (int j = 0; j < 49; j++) {
          printf("%d: %f\n", j, output[j]);
       }
    }
1 голос
/ 07 мая 2020

Удалите все объявления переменных вне и до for l oop, например:

int main (int argc, char* argv[]) {

   float input[49] = { 0.0 };
   float output[49] = {0.0};//also needs to be initialized
   //and others...

   for(int i = 0; i < 3; i++)
    {
        printf("Iteration: %d\n", i);
        ....

Сделайте то же самое для любых вызовов, которые создают повторно используемые объекты или выделяют память. Повторное объявление повторно используемых объектов в al oop (без их освобождения перед повторным объявлением) может иметь результаты, аналогичные вызову malloc в al oop, вместо использования realloc для последующих вызовов.

Ваш фрагмент кода показывает, что вы создали и удалили следующее внутри l oop:

    TfLiteInterpreterDelete(interpreter);
    TfLiteInterpreterOptionsDelete(options);
    TfLiteModelDelete(model);

Вызов в al oop также может быть проблематичным c.

TfLiteTensor* input_tensor = TfLiteInterpreterGetInputTensor(interpreter, 0);

input_tensor, я считаю, что его следует создать один раз, а затем в l oop изменить размер по мере необходимости.

По предоставленной вами ссылке:

// NOTE: After a resize, the client *must* explicitly allocate tensors before
// attempting to access the resized tensor data or invoke the interpreter.
// REQUIRES: 0 <= input_index < TfLiteInterpreterGetInputTensorCount(tensor)
TFL_CAPI_EXPORT extern TfLiteStatus TfLiteInterpreterResizeInputTensor(
    TfLiteInterpreter* interpreter, int32_t input_index, const int* input_dims,
    int32_t input_dims_size);  

Изменить: Еще один элемент, который кажется странным:

const TfLiteTensor* output_tensor = TfLiteInterpreterGetOutputTensor(interpreter, 14);

Модификатор const кажется странным спутником output_tensor. Казалось бы, если эта переменная изменится внутри l oop, то не стоит менять на const.

...