You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							160 lines
						
					
					
						
							5.0 KiB
						
					
					
				
			
		
		
	
	
							160 lines
						
					
					
						
							5.0 KiB
						
					
					
				#include "tfmodel.h"
 | 
						|
#include <string>
 | 
						|
#include <string.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <stdexcept>
 | 
						|
#include "common/util.h"
 | 
						|
#include "common/swaglog.h"
 | 
						|
#include <cassert>
 | 
						|
 | 
						|
void TFModel::status_check() const {
 | 
						|
  if (TF_GetCode(this->status) != TF_OK) {
 | 
						|
    throw std::runtime_error(TF_Message(status));
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
TF_Tensor *TFModel::allocate_tensor_for_output(TF_Output out, float *dat) {
 | 
						|
  int num_dims = TF_GraphGetTensorNumDims(graph, out, status);
 | 
						|
  status_check();
 | 
						|
  int64_t *dims = new int64_t[num_dims];
 | 
						|
  TF_GraphGetTensorShape(graph, out, dims, num_dims, status);
 | 
						|
  status_check();
 | 
						|
  dims[0] = 1;
 | 
						|
 | 
						|
  int total = 1;
 | 
						|
  for (int i = 0; i < num_dims; i++) total *= dims[i];
 | 
						|
  //printf("dims %d total %d wdat %p\n", num_dims, total, dat);
 | 
						|
 | 
						|
  // don't deallocate the buffers
 | 
						|
  auto d = [](void* ddata, size_t, void* arg) {};
 | 
						|
  TF_Tensor *ret = TF_NewTensor(TF_FLOAT, dims, num_dims, (void*)dat, sizeof(float)*total, d, NULL);
 | 
						|
 | 
						|
  //TF_Tensor *ret = TF_AllocateTensor(TF_FLOAT, dims, num_dims, sizeof(float)*total);
 | 
						|
  //memcpy(TF_TensorData(ret), dat, sizeof(float)*total);
 | 
						|
 | 
						|
  assert(ret);
 | 
						|
  delete[] dims;
 | 
						|
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
TFModel::TFModel(const char *path, float *_output, size_t _output_size, int runtime) {
 | 
						|
  // load model
 | 
						|
  {
 | 
						|
    TF_Buffer* buf;
 | 
						|
    size_t model_size;
 | 
						|
    char tmp[1024];
 | 
						|
    snprintf(tmp, sizeof(tmp), "%s.pb", path);
 | 
						|
    LOGD("loading model %s", tmp);
 | 
						|
    uint8_t *model_data = (uint8_t *)read_file(tmp, &model_size);
 | 
						|
    assert(model_data);
 | 
						|
    buf = TF_NewBuffer();
 | 
						|
    buf->data = model_data;
 | 
						|
    buf->length = model_size;
 | 
						|
    buf->data_deallocator = [](void *data, size_t) { free(data); };
 | 
						|
    LOGD("loaded model of size %d", model_size);
 | 
						|
 | 
						|
    // import graph
 | 
						|
    status = TF_NewStatus();
 | 
						|
    graph = TF_NewGraph();
 | 
						|
    TF_ImportGraphDefOptions *opts = TF_NewImportGraphDefOptions();
 | 
						|
    // TODO: fix the GPU, currently it hangs if you set this to /gpu:0
 | 
						|
    //TF_ImportGraphDefOptionsSetDefaultDevice(opts, "/cpu:0");
 | 
						|
    TF_GraphImportGraphDef(graph, buf, opts, status);
 | 
						|
    TF_DeleteImportGraphDefOptions(opts);
 | 
						|
    TF_DeleteBuffer(buf);
 | 
						|
    status_check();
 | 
						|
    LOGD("imported graph");
 | 
						|
  }
 | 
						|
 | 
						|
  // set up session
 | 
						|
  TF_SessionOptions* sess_opts = TF_NewSessionOptions();
 | 
						|
 | 
						|
  // don't use all GPU memory
 | 
						|
  /*uint8_t config[15] = {0x32, 0xb, 0x9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x20, 0x1, 0x38, 0x1};
 | 
						|
  double gpu_memory_fraction = 0.2;
 | 
						|
  auto bytes = reinterpret_cast<std::uint8_t*>(&gpu_memory_fraction);
 | 
						|
  for (std::size_t i = 0; i < sizeof(gpu_memory_fraction); ++i) {
 | 
						|
    config[i + 3] = bytes[i];
 | 
						|
  }
 | 
						|
  TF_SetConfig(sess_opts, config, sizeof(config), status);
 | 
						|
  status_check();*/
 | 
						|
 | 
						|
  // make session
 | 
						|
  session = TF_NewSession(graph, sess_opts, status);
 | 
						|
  TF_DeleteSessionOptions(sess_opts);
 | 
						|
  status_check();
 | 
						|
 | 
						|
  // find tensors
 | 
						|
  // TODO: make this generic
 | 
						|
  input_operation = {TF_GraphOperationByName(graph, "lambda/div"), 0};
 | 
						|
  if (input_operation.oper == NULL) {
 | 
						|
    input_operation = {TF_GraphOperationByName(graph, "vision_lambda/div"), 0};
 | 
						|
  }
 | 
						|
  assert(input_operation.oper != NULL);
 | 
						|
 | 
						|
  output_operation = {TF_GraphOperationByName(graph, "outputs/outputs/Identity"), 0};
 | 
						|
  if (output_operation.oper == NULL) {
 | 
						|
    output_operation = {TF_GraphOperationByName(graph, "outputs/concat"), 0};
 | 
						|
  }
 | 
						|
  assert(output_operation.oper != NULL);
 | 
						|
 | 
						|
  // output tensor is good to bind now
 | 
						|
  output = _output;
 | 
						|
  output_size = _output_size;
 | 
						|
}
 | 
						|
 | 
						|
TFModel::~TFModel() {
 | 
						|
  TF_DeleteSession(session, status);
 | 
						|
  status_check();
 | 
						|
  TF_DeleteGraph(graph);
 | 
						|
  TF_DeleteStatus(status);
 | 
						|
}
 | 
						|
 | 
						|
void TFModel::addRecurrent(float *state, int state_size) {
 | 
						|
  rnn_operation.oper = TF_GraphOperationByName(graph, "rnn_state");
 | 
						|
  rnn_operation.index = 0;
 | 
						|
  assert(rnn_operation.oper != NULL);
 | 
						|
 | 
						|
  rnn_input_buf = state;
 | 
						|
}
 | 
						|
 | 
						|
void TFModel::addDesire(float *state, int state_size) {
 | 
						|
  desire_operation.oper = TF_GraphOperationByName(graph, "desire");
 | 
						|
  desire_operation.index = 0;
 | 
						|
  assert(desire_operation.oper != NULL);
 | 
						|
 | 
						|
  desire_input_buf = state;
 | 
						|
}
 | 
						|
 | 
						|
void TFModel::execute(float *net_input_buf) {
 | 
						|
  TF_Tensor *input_tensor = allocate_tensor_for_output(input_operation, net_input_buf);
 | 
						|
  assert(input_tensor);
 | 
						|
  TF_Tensor *output_tensor = NULL;
 | 
						|
 | 
						|
  if (rnn_input_buf == NULL) {
 | 
						|
    TF_SessionRun(session, NULL,
 | 
						|
      &input_operation, &input_tensor, 1,
 | 
						|
      &output_operation, &output_tensor, 1,
 | 
						|
      NULL, 0, NULL, status);
 | 
						|
  } else {
 | 
						|
    //printf("%f %f %f\n", net_input_buf[0], rnn_input_buf[0], desire_input_buf[0]);
 | 
						|
    TF_Tensor *rnn_tensor = allocate_tensor_for_output(rnn_operation, rnn_input_buf);
 | 
						|
    TF_Tensor *desire_tensor = allocate_tensor_for_output(desire_operation, desire_input_buf);
 | 
						|
    TF_Output io[] = {input_operation, rnn_operation, desire_operation};
 | 
						|
    TF_Tensor* id[] = {input_tensor, rnn_tensor, desire_tensor};
 | 
						|
    TF_SessionRun(session, NULL,
 | 
						|
      io, id, 3,
 | 
						|
      &output_operation, &output_tensor, 1,
 | 
						|
      NULL, 0, NULL, status);
 | 
						|
    TF_DeleteTensor(rnn_tensor);
 | 
						|
    TF_DeleteTensor(desire_tensor);
 | 
						|
  }
 | 
						|
  TF_DeleteTensor(input_tensor);
 | 
						|
  status_check();
 | 
						|
  assert(output_tensor);
 | 
						|
  memcpy((void*)output, TF_TensorData(output_tensor), output_size*sizeof(float));
 | 
						|
  TF_DeleteTensor(output_tensor);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 |