TF_SessionRun из TensorFlow C API не может запустить сеанс, созданный в другой функции-члене - PullRequest
0 голосов
/ 06 августа 2020

У меня есть класс C ++ RF с двумя функциями-членами: load () для загрузки сохраненной модели (.pb) и detect () для многократного запуска модели для вывода. У меня есть еще один класс C ++ IMPL с двумя функциями: одна initialize (), а другая create (). Один объект РФ является участником IMPL. Когда я запускаю RF :: load () и RF :: detect () в одной и той же функции IMPL, он работает нормально. Однако, когда я вызываю RF :: load () в IMPL :: initialize () и RF :: detect () в IMPL :: create (), TF_SessionRun () зависает без генерации каких-либо выходных данных или ошибок. Что не так с моим кодом или TF_SessionRun ()?

class RF
{
  public:
    RF(){}
    ~RF();
    int load();
    int detect(cv::Mat Image&);

    const char* saved_model_dir = "path/";// set model path 
    const char* tags = "serve";    
    int ntags = 1;

  private:
    const int NumInputs = 1;
    const int NumOutputs = 1;
    const unsigned short int LengthFV = 16;
    
    TF_Graph* Graph;
    TF_Status* Status;
    TF_Session* Session;
    TF_SessionOptions* SessionOpts;
    TF_Buffer* RunOpts;
    TF_Output* Input;
    TF_Output* Output;
    TF_Tensor** InputValues;
    TF_Tensor** OutputValues;
    TF_Tensor* vecTensor;
    TF_Tensor * imgTensor;
};

RF::~RF()
{
  // release memory;
}

int RF::load()
{
  Graph = TF_NewGraph();
  Status = TF_NewStatus();
  SessionOpts = TF_NewSessionOptions();
  RunOpts = NULL;

  Session = TF_LoadSessionFromSavedModel(SessionOpts, RunOpts, saved_model_dir, &tags, ntags, Graph, NULL, Status);
  if(TF_GetCode(Status) != TF_OK) {
    std::cout << "\nERROR: Failed to load SavedModel." << TF_Message(Status);
    return -1;  }

  // prepare input and output tensors
  Input = new TF_Output[NumInputs];// input tensor
  Output = new TF_Output[NumOutputs];// output tensor

  TF_Output t0 = {TF_GraphOperationByName(Graph, "serving_default_input_image"), 0};  
  if(t0.oper == NULL) {
    std::cout << "\nERROR: Failed TF_GraphOperationByName serving_default_input_image.";
    return -1;  }
  Input[0] = t0;       
    
  TF_Output t2 = {TF_GraphOperationByName(Graph, "StatefulPartitionedCall"), 0};  
  if(t2.oper == NULL) {
    std::cout << "\nERROR: Failed TF_GraphOperationByName StatefulPartitionedCall.";   
    return -1;  }
  Output[0] = t2;

  // allocate data for input and output tensors
  InputValues  = (TF_Tensor**)new TF_Tensor*[NumInputs];
  OutputValues = (TF_Tensor**)new TF_Tensor*[NumOutputs];

  int64_t dims_vector[] = {1, LengthFV};// depends on the output of retinaface
  unsigned short int dim = 2;
  std::vector<float> output_buffer(LengthFV);
  vecTensor = TF_NewTensor(TF_FLOAT, dims_vector, dim, output_buffer.data(), LengthFV*sizeof(float), &NoOpDeallocator, 0);
  if (vecTensor == NULL)  {
    std::cout << "\nERROR: Failed generation of TF_Tensor* vecTensor."; 
    return -1;  }
  OutputValues[0] = vecTensor;
    
  return 0;    
}

int RF::detect(cv::Mat& img)
{
  int iro = img.height;
  int ico = img.width;
  int ich = 3;// channels
  unsigned short int batches = 1;
  unsigned short int dims = 4;
  int64_t dims_img[] = {batches, iro, ico, ich};// {1, rows, cols, 3}
  unsigned int isi = iro * ico * ich;// size
  std::vector<float> ppm_buffer(isi);
    float* ppm_data=ppm_buffer.data();
  for(int i=0; i<isi; i++)
    ppm_data[i] = img.data.get()[i];// copy img.data to ppm_buffer

  // create new tensor and assign to InputValues
  //std::vector<float> input_buffer(this->input_size);
  imgTensor = TF_NewTensor(TF_FLOAT, dims_img, dims, ppm_buffer.data(), isi*sizeof(float), &NoOpDeallocator, 0);
  if (imgTensor == NULL)  {
    std::cout << "\nERROR: Failed generation of TF_Tensor* imgTensor.";
    return -1;  }     
  InputValues[0] = imgTensor; 

  // run session
  std::cout << "\nRunning TF_SessionRun...";
  TF_SessionRun(Session, NULL,  Input,  InputValues, NumInputs,  Output,  OutputValues, NumOutputs, NULL, 0,NULL ,  Status);
  if(TF_GetCode(Status) == TF_OK)
    std::cout << "\nSUCCESS: TF_SessionRun is OK.";
  else
  {
    std::cout << "\nERROR: " << TF_Message(Status);
    return -1;
  }

  return 0;
}
class IMPL
{
   private:
   RF rf;

   public:
   int initialize(int status)
   {
      if (rf.load() != 0 );
      return -1;
      else
      return 0;
   }
   int create(cv::Mat& image)
   {
      if( rf.detect(image) != 0 )
      return -1;
      else
      return 0;
   }
};
main()
{
   IMPL impl;
   impl.initialize();
   impl.create();
}

1 Ответ

0 голосов
/ 07 августа 2020

Причина в использовании нескольких процессов. initialize () и create () использовали разные идентификаторы процесса. Указатели в create () ни на что не указывали. Следующее решение может быть не изящным, но оно решило мою проблему. Я изменил create () и его работу (теперь я могу загружать один раз и использовать несколько раз).


    int create(cv::Mat& image)
    {
        if ( !rf.initialized )// add bool initialized = false; to RF
        {
            if (rf.load() != 0)
                std::cout << "\nERROR: loading failed.";
            else
                std::cout <<"\nRF loaded.";
            rf.initialized = true;
        }
    if( rf.detect(image) != 0 )
        return -1;
    else
        return 0;
    }

...