0

I have a C++ class RF with two member functions: load() for loading savedmodel (.pb) and detect() for running the model multiple times for inference. I have another C++ class IMPL with two functions: one initialize() and the other create(). One object of RF is a member of IMPL. When I run RF::load() and RF::detect() within the same function of IMPL, it is working fine. However, when I call RF::load() in IMPL::initialize() and RF::detect() in IMPL::create(), the TF_SessionRun() freezes without generating any output or error. What is wrong with my code or 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();
}
fisakhan
  • 704
  • 1
  • 9
  • 27

1 Answers1

1

The reason was the use of multiple processes. initialize() and create() were using different process IDs. The pointers in create() were pointing to nothing. The following solution may not be elegant but it solved my problem. I modified the create() and its working (I can now load once and use multiple times).


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

fisakhan
  • 704
  • 1
  • 9
  • 27