TF Lite C API在第二次迭代时崩溃。

问题描述 投票:0回答:2

我正在尝试使用TF Lite的C API来循环执行推理,比如我设置了解释器,每隔一秒左右给他输入一次,以获得预测结果。

为此,我建立了 libtensorflowlite_c.so 通过巴塞尔。如文件所述 此处我尝试像这样做推理,但在for循环中模拟循环执行。

#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;
}

第一次迭代运行良好,并返回了一些东西。但在第二次迭代时,当我呼叫 TfLiteTensorCopyToBuffer(output_tensor, output, 49 * sizeof(float));. 原因是之前的函数 TfLiteInterpreterGetOutputTensor 返回一个nullpointer。

我期望多次运行这个函数而不会出现任何问题,因为我在for-loop结束时销毁了所有变量的旧实例,因此每次都会启动一个新的解释器。显然,事实并非如此。

谁能提供一些指导?另外,我知道我可能不需要在每次迭代时都创建一个解释器,但我想确保当我重新开始时,所有的东西都是新创建的。

EDIT.我试着重写了代码,使之成为一个新的解释器,但我想确保当我重新开始时,所有的东西都是新创建的。

我试着重写了代码,以排除实际循环中不必要的部分。

#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;
}
c tensorflow tensorflow-lite
2个回答
1
投票

删除所有变量声明外和之前的 for 循环,例如

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);
        ....

对任何创建可重用对象或分配内存的调用也要这样做。 在循环中重新声明可重用的对象(在重新声明之前不释放它们),其结果与调用 malloc 循环,而不是使用 realloc 的后续调用。

您的代码片段显示您有 创建删除 在循环中调用以下内容。

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

在循环中调用它也可能会有问题。

TfLiteTensor* input_tensor = TfLiteInterpreterGetInputTensor(interpreter, 0);

input_tensor我认为应该先创建一次,然后在循环中根据需要调整大小。

从你提供的链接来看。

// 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. 如果这个变量在循环中会发生变化,那么就不应该修改为 const.


1
投票

你的代码运行良好,如果 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]);
       }
    }
© www.soinside.com 2019 - 2024. All rights reserved.