runtime.py 3.15 KB
Newer Older
1
"""Intrinsics of TVM-Python Hybrid Script for Python emulation runtime"""
2 3

import numpy
4
from .. import target
5

6 7 8 9 10

class bind(object): #pylint: disable=invalid-name
    """GPU bind software emulataion runtime."""
    def __init__(self, _, ext):
        self.ext = ext
11 12 13 14

    def __iter__(self):
        i = 0
        while i < self.ext:
15
            yield i
16 17 18
            i += 1


19
def allocate(shape, dtype='float32', scope='global'): #pylint: disable=unused-argument
20 21 22 23 24 25 26 27
    """Allocate a buffer with given shape

    Parameters
    ----------
    shape: Tuple
        The shape of the tensor to be allocated
    dtype: string
        The data type of the tensor
28 29
    scope: string
        The storage scope of the tensor
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75

    Returns
    -------
    tensor: numpy.array
        The tensor allocated
    """
    return numpy.zeros(shape).astype(dtype)


def popcount(x):
    """
    Count ones in the binary representation of number x

    Parameters
    ----------
    x: Integer
        The number to be counted

    Returns
    -------
    cnt: Integer
        The number of ones in the binary representation of number x
    """
    cnt = 0
    while x:
        x -= x & -x
        cnt += 1
    return cnt


def sigmoid(x):
    """
    Sigmoid function of x, aka 1/(1+exp(-x)).

    Parameters
    ----------
    x: a real number

    Returns
    -------
    res: a real number
        The result of sigmoid function
    """
    return 1 / (1 + numpy.exp(-x))


76 77 78 79 80
def max_num_threads(allow_none=True):
    """Get max number of threads for GPU targets."""
    return target.current_target(allow_none).max_num_threads


81
HYBRID_GLOBALS = {
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
    'unroll'         : range,
    'vectorize'      : range,
    'parallel'       : range,
    'const_range'    : range,
    'bind'           : bind,
    'allocate'       : allocate,
    'output_tensor'  : allocate,
    'sqrt'           : numpy.sqrt,
    'log'            : numpy.log,
    'tanh'           : numpy.tanh,
    'power'          : numpy.power,
    'exp'            : numpy.exp,
    'sigmoid'        : sigmoid,
    'popcount'       : popcount,
    'likely'         : lambda cond: cond,
    'uint8'          : numpy.uint8,
    'uint16'         : numpy.uint16,
    'uint32'         : numpy.uint32,
    'uint64'         : numpy.uint64,
    'int8'           : numpy.int8,
    'int16'          : numpy.int16,
    'int32'          : numpy.int32,
    'int64'          : numpy.int64,
    'float16'        : numpy.float16,
    'float32'        : numpy.float32,
    'float64'        : numpy.float64,
    'ceil_div'       : lambda a, b: (a + b - 1) // b,
    'max_num_threads': max_num_threads
110
}
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130


def _enter_hybrid_runtime(func):
    """Put hybrid runtime variables into the global scope"""
    _globals = func.__globals__
    intersect = []
    for elem in list(HYBRID_GLOBALS.keys()):
        if elem in _globals.keys():
            intersect.append((elem, _globals[elem]))
        _globals[elem] = HYBRID_GLOBALS[elem]
    return intersect


def _restore_runtime(func, intersect):
    """Rollback the modification caused by hybrid runtime"""
    _globals = func.__globals__
    for elem in list(HYBRID_GLOBALS.keys()):
        _globals.pop(elem)
    for k, v in intersect:
        _globals[k] = v