TF Lite C API 在第二次迭代时崩溃
TF Lite C API crashes on second iteration
我正在尝试使用 TF Lite 的 C API 循环执行推理,例如我设置了解释器并每隔一秒左右向他提供输入以获得预测。
为此,我通过 bazel 构建了 libtensorflowlite_c.so
。如记录 here,我尝试像这样进行推理,但在 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;
}
第一次迭代 运行 很好 returns 一些。但是在第二次迭代中,我在调用 TfLiteTensorCopyToBuffer(output_tensor, output, 49 * sizeof(float));
时得到了一个 SegFault。原因是前面的函数 TfLiteInterpreterGetOutputTensor
returns 一个空指针。
我希望 运行 这多次没有任何问题,因为我在 for 循环结束时销毁了所有旧的变量实例,因此每次都启动一个新的解释器。显然,事实并非如此。
有人可以提供任何指导吗?此外,我知道我可能不必在每次迭代时都创建一个解释器,但我想确保在我重新开始时所有内容都是新创建的。
编辑:
我尝试重写代码以从实际循环中排除不必要的部分:
#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;
}
删除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
,我相信应该创建一次,然后在循环中根据需要调整大小。
根据您提供的link:
// 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
.
如果 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]);
}
}
我正在尝试使用 TF Lite 的 C API 循环执行推理,例如我设置了解释器并每隔一秒左右向他提供输入以获得预测。
为此,我通过 bazel 构建了 libtensorflowlite_c.so
。如记录 here,我尝试像这样进行推理,但在 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;
}
第一次迭代 运行 很好 returns 一些。但是在第二次迭代中,我在调用 TfLiteTensorCopyToBuffer(output_tensor, output, 49 * sizeof(float));
时得到了一个 SegFault。原因是前面的函数 TfLiteInterpreterGetOutputTensor
returns 一个空指针。
我希望 运行 这多次没有任何问题,因为我在 for 循环结束时销毁了所有旧的变量实例,因此每次都启动一个新的解释器。显然,事实并非如此。
有人可以提供任何指导吗?此外,我知道我可能不必在每次迭代时都创建一个解释器,但我想确保在我重新开始时所有内容都是新创建的。
编辑:
我尝试重写代码以从实际循环中排除不必要的部分:
#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;
}
删除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
,我相信应该创建一次,然后在循环中根据需要调整大小。
根据您提供的link:
// 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
.
如果 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]);
}
}