提交 9f5cd455 authored 作者: james@mackie's avatar james@mackie

first serious attempt at handling compiled code and blas using environment variables

上级 50da7310
- optimize a**2 -> sqr(a)
- add __getitem__ to NumpyR (including derivative) by storing the integer / slice object
import os # for building the location of the .omega/omega_compiled cache directory import os # for building the location of the .omega/omega_compiled cache directory
import sys # for adding the inline code cache to the include path import sys # for adding the inline code cache to the include path
import platform #
import os import os
import sys import sys
...@@ -45,18 +46,74 @@ literals_id_db = weakref.WeakValueDictionary() ...@@ -45,18 +46,74 @@ literals_id_db = weakref.WeakValueDictionary()
# see TRAC(#31) # see TRAC(#31)
default_input_scalar_dtype = 'float64' default_input_scalar_dtype = 'float64'
# BLAS Support def _constant(f):
# These should be used by dependent modules to link blas functions. """Return a function that always returns its first call value
# - used by dot(), gemm() """
_blas_headers = ['"/home/bergstra/cvs/lgcm/omega/cblas.h"'] def rval(*args, **kwargs):
_blas_libs = ['mkl', 'm'] if not hasattr(f, 'rval'):
f.rval = f(*args, **kwargs)
return f.rval
return rval
@_constant
def _blas_headers():
"""Return a list of strings which should be #include-ed into C files.
Default: [''], but environment variable OMEGA_CBLAS_H overrides this.
"""
envvar = os.getenv('OMEGA_CBLAS_H')
if envvar is None:
return []
else:
return [envvar]
@_constant
def _blas_libs():
"""Return a list of libraries against which an Op's object file should be
linked to benefit from a BLAS implementation.
Default: ['mkl','m'], but environment variable OMEGA_BLAS_LDFLAGS overrides this.
"""
if os.getenv('OMEGA_BLAS_LDFLAGS'):
return os.getenv('OMEGA_BLAS_LDFLAGS').split()
else:
return ['mkl', 'm']
@_constant
def _compile_dir():
"""Return the directory in which scipy.weave should store code objects.
If the environment variable OMEGA_COMPILEDIR is set, its value is returned.
If not, a directory of the form $HOME/.omega/compiledir_<platform Id>.
As a test, this function touches the file __init__.py in the returned
directory, and raises OSError if there's a problem.
A directory coming from OMEGA_COMPILEDIR is not created automatically, but
a directory in $HOME/.omega is created automatically.
This directory is appended to the sys.path search path before being
returned, if the touch was successful.
"""
if os.getenv('OMEGA_COMPILEDIR'):
cachedir = os.getenv('OMEGA_COMPILEDIR')
else:
# use (and possibly create) a default code cache location
platform_id = platform.platform() + '-' + platform.processor()
cachedir = os.path.join(os.getenv('HOME'), '.omega', 'compiledir_'+platform_id)
if not os.access(cachedir, os.R_OK | os.W_OK):
#this may raise a number of problems, I think all of which are serious.
os.makedirs(cachedir, 7<<6)
cachedir_init = cachedir+'/__init__.py'
touch = os.system('touch '+cachedir_init)
if touch:
raise OSError('touch %s returned %i' % (cachedir_init, touch))
if cachedir not in sys.path:
sys.path.append(cachedir)
return cachedir
# WEAVE CACHE
#_home_omega = os.path.join(os.getenv('HOME'), '.omega')
_home_omega = os.path.join('/home/bergstra/.omega')
_compiled = 'omega_compiled'
_home_omega_compiled = os.path.join(_home_omega, _compiled)
sys.path.append(_home_omega) # J - is this a good idea??
def input(x): def input(x):
#NB: #NB:
...@@ -269,8 +326,8 @@ class omega_op(gof.PythonOp): ...@@ -269,8 +326,8 @@ class omega_op(gof.PythonOp):
instantiate.customize.add_library(lib) instantiate.customize.add_library(lib)
mod.add_function(instantiate) mod.add_function(instantiate)
mod.compile(location = _home_omega_compiled) mod.compile(location = _compile_dir())
module = __import__("%s.%s" % (_compiled, module_name), {}, {}, [module_name]) module = __import__("%s" % (module_name), {}, {}, [module_name])
def creator(): def creator():
return module.instantiate(*[x.data for x in self.inputs + self.outputs]) return module.instantiate(*[x.data for x in self.inputs + self.outputs])
...@@ -648,6 +705,9 @@ class NumpyR(gof.PythonR): ...@@ -648,6 +705,9 @@ class NumpyR(gof.PythonR):
def __copy__(self): return array_copy(self) def __copy__(self): return array_copy(self)
#def __getitem__(self, item): return get_slice(self, item)
#def __getslice__(self, item): return get_slice(self, item)
def wrap_producer(f): def wrap_producer(f):
class producer(omega_op): class producer(omega_op):
...@@ -1034,9 +1094,9 @@ class dot(omega_op): ...@@ -1034,9 +1094,9 @@ class dot(omega_op):
shape = (x[2][0], y[2][1]) shape = (x[2][0], y[2][1])
return (numpy.ndarray, upcast(x[1], y[1]), shape) return (numpy.ndarray, upcast(x[1], y[1]), shape)
def c_headers(self): def c_headers(self):
return _blas_headers return _blas_headers()
def c_libs(self): def c_libs(self):
return _blas_libs return _blas_libs()
def c_impl((_x, _y), (_z, )): def c_impl((_x, _y), (_z, )):
return blas_code.gemm_xyz('', '1.0', '0.0') return blas_code.gemm_xyz('', '1.0', '0.0')
...@@ -1070,9 +1130,9 @@ class gemm(omega_op, inplace): ...@@ -1070,9 +1130,9 @@ class gemm(omega_op, inplace):
def alloc(self, except_list): def alloc(self, except_list):
self.outputs[0].data = self.inputs[0].data self.outputs[0].data = self.inputs[0].data
def c_headers(self): def c_headers(self):
return _blas_headers return _blas_headers()
def c_libs(self): def c_libs(self):
return _blas_libs return _blas_libs()
def c_impl((_zin, _a, _x, _y, _b), (_z,)): def c_impl((_zin, _a, _x, _y, _b), (_z,)):
check_ab = """ check_ab = """
{ {
...@@ -1221,7 +1281,6 @@ pow_scalar_r_inplace = pow_scalar_r.inplace_version() ...@@ -1221,7 +1281,6 @@ pow_scalar_r_inplace = pow_scalar_r.inplace_version()
pow_scalar_r_inplace.set_impl(tensor_scalar_impl(numpy.ndarray.__ipow__)) pow_scalar_r_inplace.set_impl(tensor_scalar_impl(numpy.ndarray.__ipow__))
## Others ## ## Others ##
class minmax(elemwise): class minmax(elemwise):
...@@ -1260,7 +1319,6 @@ class fill(elemwise): ...@@ -1260,7 +1319,6 @@ class fill(elemwise):
ifill = fill.inplace_version() ifill = fill.inplace_version()
class sum(elemwise): class sum(elemwise):
impl = numpy.sum impl = numpy.sum
def grad(x, gz): def grad(x, gz):
...@@ -1273,20 +1331,6 @@ class sum(elemwise): ...@@ -1273,20 +1331,6 @@ class sum(elemwise):
return "sump[0] += x_i;" return "sump[0] += x_i;"
## Array slicing ##
class get_slice(omega_op, view):
def grad(x, gz):
raise NotImplementedError()
def impl(x, dims):
return x.__getitem__(*dims)
# class set_slice(omega_op, inplace):
# def impl(x, dims):
# x.__setitem__(*dims)
# return x
add = scalar_switch(add_elemwise, add_scalar, add_scalar) add = scalar_switch(add_elemwise, add_scalar, add_scalar)
add_inplace = scalar_switch(add_elemwise_inplace, add_scalar_inplace) add_inplace = scalar_switch(add_elemwise_inplace, add_scalar_inplace)
...@@ -1303,4 +1347,3 @@ pow = scalar_switch(pow_elemwise, pow_scalar_r, pow_scalar_l) ...@@ -1303,4 +1347,3 @@ pow = scalar_switch(pow_elemwise, pow_scalar_r, pow_scalar_l)
pow_inplace = scalar_switch(pow_elemwise_inplace, pow_scalar_r_inplace) pow_inplace = scalar_switch(pow_elemwise_inplace, pow_scalar_r_inplace)
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论