Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Returning list of op names in get_graph_ops and extended error atoms to all TF error codes #6

Merged
merged 3 commits into from
May 19, 2018
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 82 additions & 8 deletions c_src/Tensorflex.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
#include <stdio.h>
#include <stdlib.h>

#define BASE_STRING_LENGTH 255

void free_buffer(void* data, size_t length) {
free(data);
}



ErlNifResourceType *graph_resource, *op_desc_resource, *tensor_resource, *session_resource, *op_resource, *buffer_resource, *status_resource, *graph_opts_resource;

void graph_destr(ErlNifEnv *env, void *res) {
Expand Down Expand Up @@ -75,7 +75,6 @@ static ERL_NIF_TERM string_constant(ErlNifEnv *env, int argc, const ERL_NIF_TERM
return enif_make_string(env, buf, ERL_NIF_LATIN1);
}


static ERL_NIF_TERM new_import_graph_def_opts(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
TF_ImportGraphDefOptions **graph_opts_resource_alloc = enif_alloc_resource(graph_opts_resource, sizeof(TF_ImportGraphDefOptions *));
Expand Down Expand Up @@ -119,6 +118,48 @@ static ERL_NIF_TERM new_op(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
return op_desc;
}

const char* error_to_string(TF_Status* status, char* error)
{
switch(TF_GetCode(status))
{
case TF_CANCELLED: strcpy(error,"cancelled");
break;
case TF_UNKNOWN: strcpy(error,"unknown");
break;
case TF_INVALID_ARGUMENT: strcpy(error,"invalid_argument");
break;
case TF_DEADLINE_EXCEEDED: strcpy(error,"deadline_exceeded");
break;
case TF_NOT_FOUND: strcpy(error,"not_found");
break;
case TF_ALREADY_EXISTS: strcpy(error, "already_exists");
break;
case TF_PERMISSION_DENIED: strcpy(error,"permission_denied");
break;
case TF_UNAUTHENTICATED: strcpy(error,"unauthenticated");
break;
case TF_RESOURCE_EXHAUSTED: strcpy(error,"resource_exhausted");
break;
case TF_FAILED_PRECONDITION: strcpy(error,"failed_precondition");
break;
case TF_ABORTED: strcpy(error,"aborted");
break;
case TF_OUT_OF_RANGE: strcpy(error,"out_of_range");
break;
case TF_UNIMPLEMENTED: strcpy(error,"unimplemented");
break;
case TF_INTERNAL: strcpy(error,"internal");
break;
case TF_UNAVAILABLE: strcpy(error,"unavailable");
break;
case TF_DATA_LOSS: strcpy(error,"data_loss");
break;
default: strcpy(error,"unlisted_code");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we could have each of those call enif_make_atom so we don't have to allocate the string in the first place, just to convert it to an atom?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed this in the latest commit. I was needlessly allocating a string for this. Renamed the function to error_to_atom now.

}

return error;
}

static ERL_NIF_TERM read_graph(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
ErlNifBinary filepath;
Expand Down Expand Up @@ -148,7 +189,10 @@ static ERL_NIF_TERM read_graph(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv

TF_GraphImportGraphDef(graph, buf, graph_opts, status);
if (TF_GetCode(status) != TF_OK) {
return enif_make_tuple2(env,enif_make_atom(env,"error"),enif_make_string(env, "Unable to import graph", ERL_NIF_LATIN1));

char error_str[BASE_STRING_LENGTH];
error_to_string(status, error_str);
return enif_make_tuple2(env,enif_make_atom(env,"error"),enif_make_atom(env,error_str));
}
else {
fprintf(stderr, "Successfully imported graph\n");
Expand All @@ -162,6 +206,39 @@ static ERL_NIF_TERM read_graph(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv

}

static ERL_NIF_TERM get_graph_ops(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
TF_Graph **graph;
enif_get_resource(env, argv[0], graph_resource, (void *) &graph);

int n_ops = 0;
size_t pos = 0;
TF_Operation *op_count;
while ((op_count = TF_GraphNextOperation(*graph, &pos)) != NULL) {
n_ops++;
}

ERL_NIF_TERM *op_list;
ERL_NIF_TERM op_list_eterm;
TF_Operation *op_temp;
ErlNifBinary erl_str;
op_list = malloc(sizeof(ERL_NIF_TERM)*n_ops);
pos = 0;

char op_name[BASE_STRING_LENGTH];
for(int i=0; i<n_ops; i++) {
op_temp = TF_GraphNextOperation(*graph, &pos);
strcpy(op_name, (char*) TF_OperationName(op_temp));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to copy the string here? Given that we are already copying it later to the binary with memcpy?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, this wasn't needed and I have fixed this in the latest commit. I apologize for the poorly written code here.

enif_alloc_binary(strlen(op_name), &erl_str);
memcpy(erl_str.data, op_name, strlen(op_name));
op_list[i] = enif_make_binary(env,&erl_str);
}

op_list_eterm = enif_make_list_from_array(env, op_list, n_ops);
free(op_list);
return op_list_eterm;
}

static ERL_NIF_TERM create_and_run_sess(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
TF_Graph **graph;
Expand Down Expand Up @@ -207,11 +284,8 @@ static ERL_NIF_TERM create_and_run_sess(ErlNifEnv *env, int argc, const ERL_NIF_
static ErlNifFunc nif_funcs[] =
{
{ "version", 0, version },
{ "new_graph", 0, new_graph },
{ "new_op", 3, new_op },
{ "read_graph", 1, read_graph },
{ "string_constant", 1, string_constant },
{ "create_and_run_sess", 3, create_and_run_sess }
{ "get_graph_ops", 1, get_graph_ops },
};

ERL_NIF_INIT(Elixir.Tensorflex, nif_funcs, res_loader, NULL, NULL, NULL)
Expand Down
18 changes: 3 additions & 15 deletions lib/tensorflex.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,12 @@ defmodule Tensorflex do
raise "NIF tf_version/0 not implemented"
end

def new_graph do
raise "NIF tf_new_graph/0 not implemented"
end

def new_op(_graph, _op, _label) do
raise "NIF tf_new_op/3 not implemented"
end

def read_graph(_filepath) do
raise "NIF read_graph/1 not implemented"
end

def string_constant(_value) do
raise "NIF tf_string_constant/1 not implemented"
def get_graph_ops(_graph) do
raise "NIF get_graph_ops/1 not implemented"
end

def create_and_run_sess(_graph, _opdesc, _tensor) do
raise "NIF tf_create_and_run_sess/3 not implemented"
end


end