Skip to content
This repository was archived by the owner on Nov 17, 2023. It is now read-only.

Update dev branch #3

Merged
merged 14 commits into from
Jul 1, 2015
Merged
Show file tree
Hide file tree
Changes from all 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
11 changes: 11 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,14 @@
dmlc-core
mshadow
config.mk

*.pyc
.Rhistory
*log
Debug
*suo

# vim
*.swp
*.swo
*.swn
19 changes: 14 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -48,20 +48,23 @@ endif

BIN = test/api_registry_test
OBJ = storage.o narray_op_cpu.o operator.o operator_cpu.o
OBJCXX11 = engine.o narray.o mxnet_api.o api_registry.o
# add threaded engine after it is done
OBJCXX11 = engine.o narray.o mxnet_api.o api_registry.o engine.o
CUOBJ = narray_op_gpu.o operator_gpu.o

SLIB = api/libmxnet.so
ALIB = api/libmxnet.a
LIB_DEP = $(DMLC_CORE)/libdmlc.a

.PHONY: clean all

all: $(OBJ) $(OBJCXX11) $(CUOBJ) $(BIN)
all: $(ALIB) $(SLIB) $(BIN)

$(DMLC_CORE)/libdmlc.a:
+ cd $(DMLC_CORE); make libdmlc.a config=$(ROOTDIR)/$(config); cd $(ROOTDIR)

storage.o: src/storage/storage.cc
engine.o: src/dag_engine/simple_engine.cc
threaded_engine.o: src/dag_engine/threaded_engine.cc src/common/concurrent_blocking_queue.h src/common/spin_lock.h
narray.o: src/narray/narray.cc
narray_op_cpu.o: src/narray/narray_op_cpu.cc src/narray/narray_op-inl.h
narray_op_gpu.o: src/narray/narray_op_gpu.cu src/narray/narray_op-inl.h
Expand All @@ -71,7 +74,10 @@ operator_gpu.o: src/operator/operator_gpu.cu
api_registry.o: src/api_registry.cc
mxnet_api.o: api/mxnet_api.cc

test/api_registry_test: test/api_registry_test.cc $(OBJ) $(OBJCXX11) $(CUOBJ)
api/libmxnet.a: $(OBJ) $(OBJCXX11) $(CUOBJ)
api/libmxnet.so: $(OBJ) $(OBJCXX11) $(CUOBJ)

test/api_registry_test: test/api_registry_test.cc api/libmxnet.a

$(BIN) :
$(CXX) $(CFLAGS) -std=c++11 -o $@ $(filter %.cpp %.o %.c %.a %.cc, $^) $(LDFLAGS)
Expand All @@ -85,12 +91,15 @@ $(OBJCXX11) :
$(SLIB) :
$(CXX) $(CFLAGS) -shared -o $@ $(filter %.cpp %.o %.c %.a %.cc, $^) $(LDFLAGS)

$(ALIB):
ar cr $@ $+

$(CUOBJ) :
$(NVCC) -c -o $@ $(NVCCFLAGS) -Xcompiler "$(CFLAGS)" $(filter %.cu, $^)

$(CUBIN) :
$(NVCC) -o $@ $(NVCCFLAGS) -Xcompiler "$(CFLAGS)" -Xlinker "$(LDFLAGS)" $(filter %.cu %.cpp %.o, $^)

clean:
$(RM) $(OBJ) $(OBJCXX11) $(BIN) $(CUBIN) $(CUOBJ) $(SLIB) *~ */*~ */*/*~
$(RM) $(OBJ) $(OBJCXX11) $(BIN) $(CUBIN) $(CUOBJ) $(SLIB) $(ALIB) *~ */*~ */*/*~ */*/*/*~
cd $(DMLC_CORE); make clean; cd -
7 changes: 3 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
# MXNet
This is an experimental project to put cxxnet and minerva together, nothing is working yet.
This is a project that combines lessons and ideas we learnt from [cxxnet](https://github.com/dmlc/cxxnet), [minerva](https://github.com/dmlc/minerva) and [purine2](https://github.com/purine/purine2).
- The interface is designed in collaboration by authors of three projects.
- Nothing is yet working

# Guidelines
* Use google c style
* Put module header in [include](include)
- move them to ```project-name/include``` when we finalized the name
* Depend on [dmlc-core](https://github.com/dmlc/dmlc-core)
* Doxygen comment every function, class and variable for the module headers
- Ref headers in [dmlc-core/include](https://github.com/dmlc/dmlc-core/tree/master/include/dmlc)
- Use the same style as dmlc-core
* Try write some use-cases of interface in [test](test)
- They do not need to link, but need to pass compile
* Minimize dependency, if possible only depend on dmlc-core
* Macro Guard CXX11 code by
- Try to make interface compile when c++11 was not avaialable(but with some functionalities pieces missing)
Expand Down
187 changes: 187 additions & 0 deletions api/mxnet_api.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,191 @@
#include <dmlc/base.h>
#include <dmlc/logging.h>
#include <mxnet/base.h>
#include <mxnet/narray.h>
#include <mxnet/api_registry.h>
#include "./mxnet_api.h"

// NOTE: all functions return 0 upon success
// consider add try/catch block for user error
// handling in the future
using namespace mxnet;

// macro to guard beginning and end section of all functions
// every function starts with API_BEGIN(); and finishes with API_END();
#define API_BEGIN() try {
#define API_END() } catch(dmlc::Error &e) { return MXHandleException(e); } return 0;

/*!
* \brief a helper function for error handling
* will set the last error to be str_set when it is not NULL
* \param str_set the error to set
* \return a pointer message to last error
*/
const char *MXSetGetLastError_(const char *str_set) {
// use last_error to record last error
static thread_local std::string last_error;
if (str_set != NULL) {
last_error = str_set;
}
return last_error.c_str();
}

/*! \brief return str message of the last error */
const char *MXGetLastError() {
return MXSetGetLastError_(NULL);
}

/*!
* \brief handle exception throwed out
* \param e the exception
* \return the return value of API after exception is handled
*/
int MXHandleException(const dmlc::Error &e) {
MXSetGetLastError_(e.what());
return -1;
}

// NOTE: return value is added in API_END
int MXNArrayCreateNone(NArrayHandle *out) {
API_BEGIN();
*out = new NArray();
API_END();
}

int MXNArrayCreateShareMem(mx_float *data,
mx_uint *shape,
mx_uint ndim,
NArrayHandle *out) {
API_BEGIN();
*out = new NArray(TBlob(data, TShape(shape, shape + ndim),
cpu::kDevMask), 0);
API_END();
}

int MXNArrayCreate(const mx_uint *shape,
mx_uint ndim,
int dev_mask,
int dev_id,
int delay_alloc,
NArrayHandle *out) {
API_BEGIN();
*out = new NArray(TShape(shape, shape + ndim),
Context(dev_mask, dev_id),
delay_alloc != 0);
API_END();
}

int MXNArrayWait(NArrayHandle handle) {
API_BEGIN();
static_cast<NArray*>(handle)->Wait();
API_END();
}

int MXNArrayWaitAll() {
API_BEGIN();
DAGEngine::Get()->WaitForAll();
API_END();
}

int MXNArrayFree(NArrayHandle handle) {
API_BEGIN();
delete static_cast<NArray*>(handle);
API_END();
}

int MXNArrayGetShape(NArrayHandle handle,
mx_uint *out_dim,
const mx_uint **out_pdata) {
API_BEGIN();
NArray *arr = static_cast<NArray*>(handle);
if (!arr->is_none()) {
const TShape &s = arr->shape();
*out_dim = s.ndim();
*out_pdata = s.data();
} else {
*out_dim = 0;
}
API_END();
}

int MXNArrayGetData(NArrayHandle handle,
mx_float **out_pdata) {
API_BEGIN();
NArray *arr = static_cast<NArray*>(handle);
if (!arr->is_none()) {
CHECK(arr->ctx().dev_mask == cpu::kDevMask)
<< "MXNArrayGetData can only be called for NArray on CPU";
const TBlob &b = arr->data();
CHECK(b.CheckContiguous());
*out_pdata = b.FlatTo2D<cpu, mx_float>().dptr_;
} else {
*out_pdata = nullptr;
}
API_END();
}

int MXNArrayGetContext(NArrayHandle handle,
int *out_dev_mask,
int *out_dev_id) {
API_BEGIN();
NArray *arr = static_cast<NArray*>(handle);
if (!arr->is_none()) {
const Context &ctx = arr->ctx();
*out_dev_mask = ctx.dev_mask;
*out_dev_id = ctx.dev_id;
} else {
*out_dev_mask = 0;
*out_dev_id = 0;
}
API_END();
}

int MXListFunctions(mx_uint *out_size,
FunctionHandle **out_array) {
API_BEGIN();
auto &vec = FunctionRegistry::List();
*out_size = static_cast<mx_uint>(vec.size());
*out_array = (FunctionHandle*)(dmlc::BeginPtr(vec));
API_END();
}

int MXGetFunction(const char *name,
FunctionHandle *out) {
API_BEGIN();
*out = FunctionRegistry::Find(name);
API_END();
}

int MXFuncGetName(FunctionHandle fun,
const char **out_name) {
API_BEGIN();
auto *f = static_cast<const FunctionRegistry::Entry *>(fun);
*out_name = f->name.c_str();
API_END();
}

int MXFuncDescribe(FunctionHandle fun,
mx_uint *num_use_vars,
mx_uint *num_scalars,
mx_uint *num_mutate_vars,
int *type_mask) {
API_BEGIN();
auto *f = static_cast<const FunctionRegistry::Entry *>(fun);
*num_use_vars = f->num_use_vars;
*num_scalars = f->num_scalars;
*num_mutate_vars = f->num_mutate_vars;
*type_mask = f->type_mask;
API_END();
}

int MXFuncInvoke(FunctionHandle fun,
NArrayHandle *use_vars,
mx_float *scalar_args,
NArrayHandle *mutate_vars) {
API_BEGIN();
auto *f = static_cast<const FunctionRegistry::Entry *>(fun);
(*f)((NArray**)(use_vars),
scalar_args,
(NArray**)(mutate_vars));
API_END();
}
41 changes: 29 additions & 12 deletions api/mxnet_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,24 @@ typedef float mx_float;
/*! \brief handle to NArray */
typedef void *NArrayHandle;
/*! \brief handle to a mxnet narray function that changes NArray */
typedef void *FunctionHandle;
typedef const void *FunctionHandle;
/*! \brief handle to a symbol that can be bind as operator */
typedef void *SymbolHandle;
/*! \brief handle to a NArrayOperator */
typedef void *OperatorHandle;
/*! \brief handle to a DataIterator */
typedef void *DataIterHandle;

/*!
* \brief return str message of the last error
* all function in this file will return 0 when success
* and -1 when an error occured,
* MXGetLastError can be called to retrieve the error
*
* this function is threadsafe and can be called by different thread
*/
MXNET_DLL const char *MXGetLastError();

//--------------------------------
// Part 1: NArray creation and deletion
//--------------------------------
Expand Down Expand Up @@ -71,13 +81,16 @@ MXNET_DLL int MXNArrayCreateShareMem(mx_float *data,
* \param ndim the dimension of the shape
* \param dev_mask device mask, specify device we want to take
* \param dev_id the device id of the specific device
* \param delay_alloc whether to delay allocation until
* the narray is first mutated
* \param out the returning handle
* \return 0 when success, -1 when failure happens
*/
MXNET_DLL int MXNArrayCreate(const mx_uint *shape,
mx_uint ndim,
int dev_mask,
int dev_id,
int delay_alloc,
NArrayHandle *out);
/*!
* \brief wait until all the operation with respect NArray
Expand Down Expand Up @@ -105,25 +118,27 @@ MXNET_DLL int MXNArrayFree(NArrayHandle handle);
* \param out_pdata pointer holder to get data pointer of the shape
* \return 0 when success, -1 when failure happens
*/
MXNET_DLL int MXNArrayGetShape(NArrayHandle *handle,
MXNET_DLL int MXNArrayGetShape(NArrayHandle handle,
mx_uint *out_dim,
mx_uint **out_pdata);
const mx_uint **out_pdata);
/*!
* \brief get the content of the data in NArray
* \param handle the handle to the narray
* \param out_pdata pointer holder to get pointer of data
* \return 0 when success, -1 when failure happens
*/
MXNET_DLL int MXNArrayGetData(NArrayHandle *handle,
MXNET_DLL int MXNArrayGetData(NArrayHandle handle,
mx_float **out_pdata);
/*!
* \brief get the device of the NArray
* \brief get the context of the NArray
* \param handle the handle to the narray
* \param out_device the output device mask
* \param out_dev_mask the output device mask
* \param out_dev_id the output device id
* \return 0 when success, -1 when failure happens
*/
MXNET_DLL int MXNArrayGetDevice(NArrayHandle *handle,
int *out_device);
MXNET_DLL int MXNArrayGetContext(NArrayHandle handle,
int *out_dev_mask,
int *out_dev_id);

//--------------------------------
// Part 2: functions on NArray
Expand Down Expand Up @@ -158,13 +173,15 @@ MXNET_DLL int MXFuncGetName(FunctionHandle fun,
* \param num_use_vars how many NArrays to be passed in as used_vars
* \param num_scalars scalar variable is needed
* \param num_mutate_vars how many NArrays to be passed in as mutate_vars
* \param type_mask the type mask of this function
* \return 0 when success, -1 when failure happens
* \sa MXFuncInvoke
*/
MXNET_DLL int MXFuncDescribeArgs(FunctionHandle fun,
mx_uint *num_use_vars,
mx_uint *num_scalars,
mx_uint *num_mutate_vars);
MXNET_DLL int MXFuncDescribe(FunctionHandle fun,
mx_uint *num_use_vars,
mx_uint *num_scalars,
mx_uint *num_mutate_vars,
int *type_mask);

/*!
* \brief invoke a function, the array size of passed in arguments
Expand Down
17 changes: 17 additions & 0 deletions api/python/mxnet/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/usr/bin/env python
# coding: utf-8
"""MXNet: a concise, fast and flexible framework for deep learning

MXNet is a project that evolves from cxxnet, minerva and purine2.
The interface is designed in collaboration by authors of three projects.

Version : 0.10
"""
from __future__ import absolute_import

from .context import Context, current_context
from .narray import NArray, _init_function_registry
from .function import _FunctionRegistry

# this is a global function registry that can be used to invoke functions
op = _init_function_registry(_FunctionRegistry())
Loading