提交 239b6d80 authored 作者: Frédéric Bastien's avatar Frédéric Bastien

Merge pull request #2117 from abergeron/dnn

Add support for subsampling and gradient to GpuDnnConv
......@@ -2,6 +2,7 @@ global-include *.txt
global-include *.c
global-include *.cu
global-include *.cuh
global-include *.h
global-include *.sh
global-include *.pkl
recursive-include docs
......
......@@ -193,7 +193,7 @@ def do_setup():
install_requires=['numpy>=1.5.0', 'scipy>=0.7.2'],
package_data={
'': ['*.txt', '*.rst', '*.cu', '*.cuh', '*.c', '*.sh', '*.pkl',
'ChangeLog'],
'*.h', 'ChangeLog'],
'theano.misc': ['*.sh']
},
scripts=['bin/theano-cache', 'bin/theano-nose', 'bin/theano-test'],
......
import numpy
import theano
from theano.gof.type import *
from theano import Op, Apply
from theano.tensor import TensorType
from theano.gof.type import CDataType
# todo: test generic
class ProdOp(Op):
__props__ = ()
def make_node(self, i):
return Apply(self, [i], [CDataType('void *', 'py_decref')()])
def c_support_code(self):
return """
void py_decref(void *p) {
Py_XDECREF((PyObject *)p);
}
"""
def c_code(self, node, name, inps, outs, sub):
return """
Py_XDECREF(%(out)s);
%(out)s = (void *)%(inp)s;
Py_INCREF(%(inp)s);
""" % dict(out=outs[0], inp=inps[0])
def c_code_cache_version(self):
return (0,)
class GetOp(Op):
__props__ = ()
def make_node(self, c):
return Apply(self, [c], [TensorType('float32', (False,))()])
def c_support_code(self):
return """
void py_decref(void *p) {
Py_XDECREF((PyObject *)p);
}
"""
def c_code(self, node, name, inps, outs, sub):
return """
Py_XDECREF(%(out)s);
%(out)s = (PyArrayObject *)%(inp)s;
Py_INCREF(%(out)s);
""" % dict(out=outs[0], inp=inps[0])
def c_code_cache_version(self):
return (0,)
def test_cdata():
i = TensorType('float32', (False,))()
c = ProdOp()(i)
i2 = GetOp()(c)
# This should be a passthrough function for vectors
f = theano.function([i], i2)
v = numpy.random.randn(9).astype('float32')
v2 = f(v)
assert (v2 == v).all()
......@@ -2,6 +2,8 @@
__docformat__ = "restructuredtext en"
from theano.compat import PY3
from theano.gof import utils
from theano.gof.utils import MethodNotDefined, object2
from theano.gof import graph
......@@ -158,7 +160,7 @@ class CLinkerType(CLinkerObject):
c_extract_code=self.c_extract(name, sub, check_input))
def c_cleanup(self, name, sub):
"""Optional: Return c code to clean up after `c_extract`.
"""Return c code to clean up after `c_extract`.
This returns C code that should deallocate whatever `c_extract`
allocated or decrease the reference counts. Do not decrease
......@@ -250,7 +252,7 @@ class PureType(object):
# If filter_inplace is defined, it will be called instead of
# filter() This is to allow reusing the old allocated memory. As
# of this writing this is used only when we transfer new data to a
# shared variable on the gpu.
# shared variable on the gpu.
#def filter_inplace(value, storage, strict=False, allow_downcast=None)
......@@ -470,3 +472,97 @@ class Generic(SingletonType):
return self.__class__.__name__
generic = Generic()
class CDataType(Type):
"""
Represents opaque C data to be passed around. The intent is to
ease passing arbitrary data between ops C code.
"""
def __init__(self, ctype, freefunc=None):
"""
Build a type made to represent a C pointer in theano.
:param ctype: The type of the pointer (complete with the `*`)
:param freefunc: a function to call to free the pointer. This
function must have a `void` return and take a
single pointer argument.
"""
assert isinstance(ctype, basestring)
self.ctype = ctype
if freefunc is not None:
assert isinstance(freefunc, basestring)
self.freefunc = freefunc
def __eq__(self, other):
return (type(self) == type(other) and
self.ctype == other.ctype,
self.freefunc == other.freefunc)
def __hash__(self):
return hash((type(self), self.ctype, self.freefunc))
def filter(self, data, strict=False, allow_downcast=None):
if data is not None:
raise TypeError("only None is valid")
def is_valid_value(self, a):
return a is None
def c_declare(self, name, sub, check_input=True):
return """
%(ctype)s %(name)s;
""" % dict(ctype=self.ctype, name=name)
def c_init(self, name, sub):
return "%(name)s = NULL;" % dict(name=name)
def c_extract(self, name, sub, check_input=True):
if PY3:
s = """
%(name)s = (%(ctype)s)PyCapsule_GetPointer(py_%(name)s, NULL);
if (%(name)s == NULL) %(fail)s
"""
else:
s = """
%(name)s = (%(ctype)s)PyCObject_AsVoidPtr(py_%(name)s);
"""
return s % dict(name=name, ctype=self.ctype, fail=sub['fail'])
def c_sync(self, name, sub):
freefunc = self.freefunc
if freefunc is None:
freefunc = "NULL"
s = """
Py_XDECREF(py_%(name)s);
if (%(name)s == NULL) {
py_%(name)s = Py_None;
Py_INCREF(py_%(name)s);
} else """
if PY3:
s += """{
py_%(name)s = PyCapsule_New((void *)%(name)s, NULL,
(void (*)(void *))%(freefunc)s);
}"""
else:
s += """{
py_%(name)s = PyCObject_FromVoidPtr((void *)%(name)s,
(void (*)(void *))%(freefunc)s);
}"""
if self.freefunc is not None:
s += """
if (py_%(name)s == NULL) { %(freefunc)s(%(name)s); }
"""
return s % dict(name=name, freefunc=freefunc)
def c_cleanup(self, name, sub):
# No need to do anything here since the CObject/Capsule will
# free the data for us when released.
return ""
def c_code_cache_version(self):
return (1,)
def __str__(self):
return "%s{%s}" % (self.__class__.__name__, self.ctype)
差异被折叠。
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论