Skip to content

Commit

Permalink
[RUNTIME][GOLANG] TVM runtime for golang v0.1 (apache#1470)
Browse files Browse the repository at this point in the history
  • Loading branch information
srkreddy1238 authored and tqchen committed Dec 9, 2018
1 parent 069aa38 commit 1cb602f
Show file tree
Hide file tree
Showing 31 changed files with 3,872 additions and 0 deletions.
64 changes: 64 additions & 0 deletions golang/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
.PHONY: clean all

TVM_BASE = $(CURDIR)/../
TARGET = gotvm
LIBS = -lm -ldl
NATIVE_SRC = tvm_runtime_pack.cc

GOPATH=$(CURDIR)/gopath
GOPATHDIR=${GOPATH}/src/${TARGET}/
CGO_CPPFLAGS="-I. -I${TVM_BASE}/ -I${TVM_BASE}/3rdparty/dmlc-core/include -I${TVM_BASE}/include -I${TVM_BASE}/3rdparty/dlpack/include/"
CGO_CXXFLAGS="-std=c++11"
CGO_CFLAGS="-I${TVM_BASE}"
CGO_LDFLAGS="-ldl -lm"

all:
@mkdir gopath 2>/dev/null || true
@mkdir gopath/src 2>/dev/null || true
@mkdir gopath/src/$(TARGET) 2>/dev/null || true
@cp src/$(TARGET).cc gopath/src/$(TARGET)
@cp src/$(TARGET).h gopath/src/$(TARGET)
@cp src/$(NATIVE_SRC) gopath/src/$(TARGET)
@cp src/*.go gopath/src/$(TARGET)
@export GOPATH=$(GOPATH); \
export CGO_CPPFLAGS=$(CGO_CPPFLAGS); \
export CGO_CXXFLAGS=$(CGO_CXXFLAGS); \
export CGO_CFLAGS=$(CGO_CFLAGS); \
export CGO_LDFLAGS=$(CGO_LDFLAGS); \
(cd $(GOPATHDIR) && go clean -cache \
&& golint && go build -o $(TARGET).a \
&& go install)
@find . -name gotvm.a
@#mkdir gopath/doc 2>/dev/null || true
@#godoc -html -goroot gopath/ gotvm | grep -v "for documentation on the gotvm command" > gopath/doc/gotvm.html
@#echo "Run 'godoc -http=:6060 -goroot=./gopath' for documentation"

samples: all
cp gopath/pkg/linux_amd64/gotvm.a sample/ -rfa
make -C sample

tests: all
@(cd sample; python3 deploy.py)
@export GOPATH=$(GOPATH); \
export CGO_CPPFLAGS=$(CGO_CPPFLAGS); \
export CGO_CXXFLAGS=$(CGO_CXXFLAGS); \
export CGO_CFLAGS=$(CGO_CFLAGS); \
export CGO_LDFLAGS=$(CGO_LDFLAGS); \
(cd $(GOPATHDIR) \
&& cp ../../../sample/deploy.so . \
&& go test -v)

clean:
@if [ -d $(GOPATHDIR) ] ; then \
export GOPATH=$(GOPATH); \
export CGO_CPPFLAGS=$(CGO_CPPFLAGS); \
export CGO_CFLAGS=$(CGO_CFLAGS); \
export CGO_LDFLAGS=$(CGO_LDFLAGS); \
(cd $(GOPATHDIR) && go clean -cache); fi
@rm -rf gopath
@make -C sample clean

lint:
@(cd src; golint)
@python3 ${TVM_BASE}/dmlc-core/scripts/lint.py gotvm cpp src/*.cc
@python3 ${TVM_BASE}/dmlc-core/scripts/lint.py gotvm cpp src/*.h
107 changes: 107 additions & 0 deletions golang/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# gotvm - Golang Frontend for TVM Runtime

This folder contain golang interface for TVM runtime. It brings TVM runtime to Golang.

- It enable c runtime api of tvm exposed to golang.
- It enables module loading (lib, graph and params) and inference operations.

## Installation

### Requirements

- go compiler (https://golang.org/) version 0.10 or above.

### Modules

- src
Module that generates golang package corresponding to the c runtime api exposed from tvm source tree.
This process build golang package _gotvm.a_

- samples
Sample golang reference application to inference through gotvm package.

### Build

Once the Requirements are installed

To build _gotvm_ package

```bash
make
```

To build and run internal tests

```bash
make tests
```

To build sample apps.

```bash
make samples
```

## Run

To Demonstrates sample TVM module compilation using python and deploy via golang.
```bash
./simple
```

To deploy a realtime module with lib, graph and param.
```bash
./complex
```

To demonstrate go function closure conversion to packed function handle.

```bash
./pack_func_convert
```

To demonstrate a packed function handle given as an argument.

```bash
pack_func_handle_arg
```

To register go function with runtime as a global function.

```bash
pack_func_register
```

To demonstrate function closure passed as argument to a function call.

```bash
./pack_func_closure_arg
```

To demonstrate function closure returned from a packed function.

```bash
./pack_func_closure_return
```

## Documentation
gotvm.go is documented with sufficient information about gotvm package.
A html version documentation can be accessed by running below command after building runtime.

```bash
godoc -http=:6060 -goroot=./gopath
```
After above command try http://127.0.0.1:6060 from any browser.

Also please refer to the sample applications under sample folder.

## Docker
Docker setup may need below additions for dependencies and environment preparation.

Please refer ```docker/install/ubuntu_install_golang.sh``` for the packages dependencies.

go compiler 1.10 on ubuntu doesn't install on standard path, hence an explicit export may be needed as shown below.

```bash
export PATH="/usr/lib/go-1.10/bin:$PATH"```
```
17 changes: 17 additions & 0 deletions golang/sample/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
.PHONY: clean all

SOURCES=$(wildcard *.go)
EXECUTABLE=$(patsubst %.go, %, $(SOURCES))

all: $(EXECUTABLE)
@golint
@python3 deploy.py

%: %.o
@go tool link -linkmode external -extld "g++" -extldflags "-ldl" -o $@ $<

%.o: %.go
@go tool compile -pack -o $@ $<

clean:
@rm -f $(EXECUTABLE) *.so *.o *.a
171 changes: 171 additions & 0 deletions golang/sample/complex.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
/*!
* Copyright (c) 2018 by Contributors
* \brief Sample golang application deployment over tvm.
* \file complex.go
*/

package main

import (
"fmt"
"io/ioutil"
"math/rand"
"./gotvm"
"runtime"
)

// NNVM compiled model paths.
const (
modLib = "./mobilenet.so"
modJSON = "./mobilenet.json"
modParams = "./mobilenet.params"
)

// main
func main() {
defer runtime.GC()
// Welcome
fmt.Printf("TVM Version : v%v\n", gotvm.TVMVersion)
fmt.Printf("DLPACK Version: v%v\n\n", gotvm.DLPackVersion)

// Query global functions available
funcNames, err := gotvm.FuncListGlobalNames()
if err != nil {
fmt.Print(err)
return
}
fmt.Printf("Global Functions:%v\n", funcNames)

// Import tvm module (so)
modp, err := gotvm.LoadModuleFromFile(modLib)
if err != nil {
fmt.Print(err)
fmt.Printf("Please copy tvm compiled modules here and update the sample.go accordingly.\n")
fmt.Printf("You may need to update modLib, modJSON, modParams, tshapeIn, tshapeOut\n")
return
}
fmt.Printf("Module Imported:%p\n", modp)
bytes, err := ioutil.ReadFile(modJSON)
if err != nil {
fmt.Print(err)
return
}
jsonStr := string(bytes)

// Load module on tvm runtime - call tvm.graph_runtime.create
funp, err := gotvm.GetGlobalFunction("tvm.graph_runtime.create")
if err != nil {
fmt.Print(err)
return
}
fmt.Printf("Calling tvm.graph_runtime.create\n")
// Call function
graphrt, err := funp.Invoke(jsonStr, modp, (int64)(gotvm.KDLCPU), (int64)(0))
if err != nil {
fmt.Print(err)
return
}
graphmod := graphrt.AsModule()
fmt.Printf("Graph runtime Created\n")

// Array allocation attributes
tshapeIn := []int64{1, 224, 224, 3}
tshapeOut := []int64{1, 1001}

// Allocate input Array
inX, err := gotvm.Empty(tshapeIn, "float32", gotvm.CPU(0))
if err != nil {
fmt.Print(err)
return
}

// Allocate output Array
out, err := gotvm.Empty(tshapeOut)
if err != nil {
fmt.Print(err)
return
}
fmt.Printf("Input and Output Arrays allocated\n")

// Get module function from graph runtime : load_params
// Read params
bytes, err = ioutil.ReadFile(modParams)
if err != nil {
fmt.Print(err)
}

// Load Params
funp, err = graphmod.GetFunction("load_params")
if err != nil {
fmt.Print(err)
return
}
fmt.Printf("Func load_params:%p\n", funp)

// Call function
_, err = funp.Invoke(bytes)
if err != nil {
fmt.Print(err)
return
}
fmt.Printf("Module params loaded\n")

// Set some data in input Array
inSlice := make([]float32, (244 * 244 * 3))
rand.Seed(10)
rand.Shuffle(len(inSlice), func(i, j int) {inSlice[i],
inSlice[j] = rand.Float32(),
rand.Float32() })
inX.CopyFrom(inSlice)

// Set Input
funp, err = graphmod.GetFunction("set_input")
if err != nil {
fmt.Print(err)
return
}

// Call function
_, err = funp.Invoke("input", inX)
if err != nil {
fmt.Print(err)
return
}

fmt.Printf("Module input is set\n")

// Run
funp, err = graphmod.GetFunction("run")
if err != nil {
fmt.Print(err)
return
}

// Call function
_, err = funp.Invoke()
if err != nil {
fmt.Print(err)
return
}
fmt.Printf("Module Executed \n")

// Call runtime function get_output
funp, err = graphmod.GetFunction("get_output")
if err != nil {
fmt.Print(err)
return
}

// Call function
_, err = funp.Invoke(int64(0), out)
if err != nil {
fmt.Print(err)
return
}
fmt.Printf("Got Module Output \n")

// Print results
outIntf, _ := out.AsSlice()
outSlice := outIntf.([]float32)
fmt.Printf("Result:%v\n", outSlice[:10])
}
Loading

0 comments on commit 1cb602f

Please sign in to comment.