Skip to content

Commit

Permalink
[MODULE] Enable OpenCL and CUDA Modules (#53)
Browse files Browse the repository at this point in the history
  • Loading branch information
tqchen authored Feb 26, 2017
1 parent efae4be commit 2f462cc
Show file tree
Hide file tree
Showing 27 changed files with 476 additions and 335 deletions.
28 changes: 0 additions & 28 deletions include/tvm/runtime/c_runtime_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -373,34 +373,6 @@ TVM_DLL int TVMFuncListGlobalNames(int *out_size,
const char*** out_array);

// Array related apis for quick proptying
/*!
* \brief Initialize certain type of devices, this may
* not be necessary for all device types. But is needed for OpenCL.
*
* \param dev_mask The device mask of device type to be initialized
* \param option_keys Additional option keys to pass.
* \param option_vals Additional option values to pass
* \param num_options Number of options to be passed into it.
* \param out_code 1: success, 0: already initialized
* \return 0 when success, -1 when failure happens
*/
TVM_DLL int TVMDeviceInit(int dev_mask,
const char** option_keys,
const char** option_vals,
int num_options,
int *out_code);


/*!
* \brief Whether the specified context is enabled.
*
* \param ctx The context to be checked.
* \param out_enabled whether the ctx is enabled.
* \return Whether the function is successful.
*/
TVM_DLL int TVMContextEnabled(TVMContext ctx,
int* out_enabled);

/*!
* \brief Allocate a nd-array's memory,
* including space of shape, of given spec.
Expand Down
7 changes: 4 additions & 3 deletions include/tvm/runtime/packed_func.h
Original file line number Diff line number Diff line change
Expand Up @@ -535,8 +535,9 @@ inline const char* TypeCode2Str(int type_code) {
}

inline std::ostream& operator<<(std::ostream& os, TVMType t) { // NOLINT(*)
os << TypeCode2Str(t.code)
<< static_cast<int>(t.bits);
os << TypeCode2Str(t.code);
if (t.code == kHandle) return os;
os << static_cast<int>(t.bits);
if (t.lanes != 1) {
os << 'x' << static_cast<int>(t.lanes);
}
Expand All @@ -559,7 +560,7 @@ inline TVMType String2TVMType(std::string s) {
t.code = kUInt; scan = s.c_str() + 4;
} else if (s.substr(0, 5) == "float") {
t.code = kFloat; scan = s.c_str() + 5;
} else if (s == "handle") {
} else if (s.substr(0, 6) == "handle") {
t.code = kHandle;
t.bits = 64; // handle uses 64 bit by default.
scan = s.c_str() + 6;
Expand Down
2 changes: 1 addition & 1 deletion python/tvm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from . import module

from . import ndarray as nd
from .ndarray import cpu, gpu, opencl, init_opencl, cl
from .ndarray import cpu, gpu, opencl, cl

from ._base import TVMError
from .api import *
Expand Down
33 changes: 1 addition & 32 deletions python/tvm/_ctypes/_ndarray.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,9 @@
import numpy as np

from .._base import _LIB, check_call
from .._base import c_array, c_str
from .._base import c_array
from ._types import TVMType, tvm_index_t


class TVMContext(ctypes.Structure):
"""TVM context strucure."""
_fields_ = [("dev_mask", ctypes.c_int),
Expand All @@ -29,12 +28,6 @@ def __repr__(self):
return "%s(%d)" % (
TVMContext.MASK2STR[self.dev_mask], self.dev_id)

@property
def enabled(self):
ret = ctypes.c_int()
check_call(_LIB.TVMContextEnabled(self, ctypes.byref(ret)))
return ret.value != 0


class TVMArray(ctypes.Structure):
"""TVMValue in C API"""
Expand Down Expand Up @@ -141,30 +134,6 @@ def sync(ctx):
check_call(_LIB.TVMSynchronize(ctx, None))


def init_opencl(**kwargs):
"""Initialize the opencl with the options.
Parameters
----------
kwargs : dict
The options
"""
keys = []
vals = []
for k, v in kwargs.items():
keys.append(c_str(k))
vals.append(c_str(v))
dev_mask = ctypes.c_int(4)
out_code = ctypes.c_int()
check_call(_LIB.TVMDeviceInit(
dev_mask,
c_array(ctypes.c_char_p, keys),
c_array(ctypes.c_char_p, vals),
ctypes.c_int(len(keys)),
ctypes.byref(out_code)))
return out_code.value != 0


class NDArrayBase(object):
"""A simple Device/CPU Array object in runtime."""
__slots__ = ["handle"]
Expand Down
34 changes: 34 additions & 0 deletions python/tvm/addon/testing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
"""Utilities to make tempdir"""
from __future__ import absolute_import as _abs
import os
import tempfile
import shutil

class TempDirectory(object):
"""Helper object to manage temp directory during testing"""
def __init__(self):
self.temp_dir = tempfile.mkdtemp()

def __del__(self):
shutil.rmtree(self.temp_dir)

def relpath(self, name):
"""Relative path in temp dir
Parameters
----------
name : str
The name of the file.
"""
return os.path.join(self.temp_dir, name)


def tempdir():
"""Return a new temp dir which deletes the contents when exit
Returns
-------
temp : TempDirectory
The temp directory object
"""
return TempDirectory()
22 changes: 17 additions & 5 deletions python/tvm/libinfo.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
# coding: utf-8
"""Information about nnvm."""
from __future__ import absolute_import
import sys
import os
import platform


def find_lib_path():
"""Find dynamic library files.
Expand All @@ -12,6 +14,7 @@ def find_lib_path():
lib_path : list(string)
List of all found path to the libraries
"""
use_runtime = os.environ.get("TVM_USE_RUNTIME_LIB", False)
curr_path = os.path.dirname(os.path.abspath(os.path.expanduser(__file__)))
api_path = os.path.join(curr_path, '../../lib/')
cmake_build_path = os.path.join(curr_path, '../../build/Release/')
Expand All @@ -26,15 +29,24 @@ def find_lib_path():
dll_path.append(os.path.join(curr_path, '../../windows', vs_configuration))
elif os.name == "posix" and os.environ.get('LD_LIBRARY_PATH', None):
dll_path.extend([p.strip() for p in os.environ['LD_LIBRARY_PATH'].split(":")])

if os.name == 'nt':
dll_path = [os.path.join(p, 'libtvm.dll') for p in dll_path]
lib_dll_path = [os.path.join(p, 'libtvm.dll') for p in dll_path]
runtime_dll_path = [os.path.join(p, 'libtvm_runtime.dll') for p in dll_path]
else:
dll_path = [os.path.join(p, 'libtvm.so') for p in dll_path]
lib_path = [p for p in dll_path if os.path.exists(p) and os.path.isfile(p)]
if len(lib_path) == 0:
lib_dll_path = [os.path.join(p, 'libtvm.so') for p in dll_path]
runtime_dll_path = [os.path.join(p, 'libtvm_runtime.so') for p in dll_path]

dll_path = runtime_dll_path if use_runtime else lib_dll_path
lib_found = [p for p in dll_path if os.path.exists(p) and os.path.isfile(p)]

if len(lib_found) == 0:
raise RuntimeError('Cannot find the files.\n' +
'List of candidates:\n' + str('\n'.join(dll_path)))
return lib_path
if use_runtime:
sys.stderr.write("Loading runtime library... this is execution only\n")
sys.stderr.flush()
return lib_found


# current version
Expand Down
1 change: 0 additions & 1 deletion python/tvm/ndarray.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
from ._ctypes._ndarray import TVMContext, TVMType, NDArrayBase
from ._ctypes._ndarray import cpu, gpu, opencl, empty, sync
from ._ctypes._ndarray import _init_ndarray_module
from ._ctypes._ndarray import init_opencl
from ._ctypes._function import Function

cl = opencl
Expand Down
2 changes: 1 addition & 1 deletion src/api/api_codegen.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ TVM_REGISTER_API(_codegen_build)
}
});

TVM_REGISTER_API(_codegen_target_enabled)
TVM_REGISTER_API(_codegen_enabled)
.set_body([](TVMArgs args, TVMRetValue *ret) {
*ret = TargetEnabled(args[0]);
});
Expand Down
7 changes: 5 additions & 2 deletions src/codegen/build_cuda.cc
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,13 @@ runtime::Module BuildCUDA(Array<LoweredFunc> funcs) {
if (const auto* f = Registry::Get("tvm_callback_cuda_postproc")) {
code = (*f)(code).operator std::string();
}

std::string fmt = "ptx";
std::string ptx;
if (const auto* f = Registry::Get("tvm_callback_cuda_compile")) {
ptx = (*f)(code).operator std::string();
// Dirty matching to check PTX vs cubin.
// TODO(tqchen) more reliable checks
if (ptx[0] != '/') fmt = "cubin";
} else {
ptx = NVRTCCompile(code);
}
Expand All @@ -80,7 +83,7 @@ runtime::Module BuildCUDA(Array<LoweredFunc> funcs) {
}
fmap[f->name] = info;
}
return CUDAModuleCreate(ptx, "ptx", fmap, code);
return CUDAModuleCreate(ptx, fmt, fmap, code);
}

TVM_REGISTER_API(_codegen_build_cuda)
Expand Down
32 changes: 0 additions & 32 deletions src/runtime/c_runtime_api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -200,38 +200,6 @@ int TVMFuncCreateFromCFunc(TVMPackedCFunc func,
API_END();
}

int TVMDeviceInit(int dev_mask,
const char** option_keys,
const char** option_vals,
int num_options,
int* out_code) {
API_BEGIN();
*out_code = 1;
switch (dev_mask) {
case kOpenCL: {
*out_code = DeviceInit<kOpenCL>(option_keys, option_vals, num_options);
break;
}
default: break;
}
API_END();
}

int TVMContextEnabled(TVMContext ctx,
int* out_enabled) {
API_BEGIN();
if (ctx.dev_mask == kGPU && TVM_CUDA_RUNTIME == 0) {
*out_enabled = 0;
} else if (ctx.dev_mask == kOpenCL && TVM_OPENCL_RUNTIME == 0) {
*out_enabled = 0;
} else {
TVM_DEVICE_SWITCH(ctx, {
*out_enabled = CheckEnabled<xpu>(ctx);
});
}
API_END();
}

int TVMArrayAlloc(const tvm_index_t* shape,
tvm_index_t ndim,
TVMType dtype,
Expand Down
16 changes: 13 additions & 3 deletions src/runtime/cuda/cuda_module.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "./cuda_module.h"

#if TVM_CUDA_RUNTIME

#include <tvm/runtime/registry.h>
#include <cuda.h>
#include <cuda_runtime.h>
Expand Down Expand Up @@ -60,7 +61,12 @@ class CUDAModuleNode : public runtime::ModuleNode {

void SaveToFile(const std::string& file_name,
const std::string& format) final {
LOG(FATAL) << "Not implemented";
std::string fmt = GetFileFormat(file_name, format);
CHECK_EQ(fmt, fmt_)
<< "Can only save to format=" << fmt_;
std::string meta_file = GetMetaFilePath(file_name);
SaveMetaDataToFile(meta_file, fmap_);
SaveBinaryToFile(file_name, data_);
}

std::string GetSource(const std::string& format) final {
Expand Down Expand Up @@ -212,9 +218,13 @@ Module CUDAModuleCreate(
// Load module from module.
Module CUDAModuleLoad(const std::string& file_name,
const std::string& format) {
std::string data;
std::unordered_map<std::string, FunctionInfo> fmap;
std::string fmt = GetFileFormat(file_name, format);
std::string data = LoadBinaryFile(file_name);
return CUDAModuleCreate(data, fmt, {{}}, std::string());
std::string meta_file = GetMetaFilePath(file_name);
LoadBinaryFromFile(file_name, &data);
LoadMetaDataFromFile(meta_file, &fmap);
return CUDAModuleCreate(data, fmt, fmap, std::string());
}

TVM_REGISTER_GLOBAL(_module_loadfile_cubin)
Expand Down
25 changes: 0 additions & 25 deletions src/runtime/device_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,31 +11,6 @@

namespace tvm {
namespace runtime {
/*!
* \brief Initialize the device.
* \param option_keys Additional option keys to pass.
* \param option_vals Additional option values to pass
* \param num_options Number of options to be passed into it.
* \return 0 if success, 1: if already initialized
* \tparam xpu The device mask.
*/
template<TVMDeviceMask xpu>
inline bool DeviceInit(const char** option_keys,
const char** option_vals,
int num_options) {
return true;
}

/*!
* \brief Whether ctx is enabled.
* \param ctx The device context to perform operation.
* \tparam xpu The device mask.
*/
template<TVMDeviceMask xpu>
inline bool CheckEnabled(TVMContext ctx) {
return true;
}

/*!
* \brief Allocate a data space on device.
* \param ctx The device context to perform operation.
Expand Down
Loading

0 comments on commit 2f462cc

Please sign in to comment.