提交 f148f376 authored 作者: Arnaud Bergeron's avatar Arnaud Bergeron

Make the GpuAlloc op act more like the tensor version.

Add tests for GpuFromCuda and CudaFromGpu (which I could not try). Add tests for GpuAlloc inspired by the tensor tests. While there adapt the makeTester function in the tensor tests for easier testing of other ops.
上级 bbe731ac
......@@ -451,17 +451,17 @@ class GpuAlloc(Op):
def make_node(self, value, *shape):
v = as_gpuarray_variable(value)
sh = [tensor.as_tensor_variable(s) for s in shape]
if v.ndim != len(shape):
raise TypeError(
'GpuAlloc requires value of same dimensions as shape',
value, len(shape))
bcast = []
for s in sh:
if v.ndim > len(shape):
raise TypeError(
'GpuAlloc value has more dimensions than arguments',
value.ndim, len(shape))
for i, s in enumerate(sh):
if s.type.dtype[:3] not in ('int', 'uint'):
raise TypeError('Shape arguments must be integers', s)
try:
const_shp = tensor.get_constant_value(s)
except tensor.NotConstantError:
const_shp = tensor.get_scalar_constant_value(s)
except tensor.NotScalarConstantError:
const_shp = None
bcast.append(numpy.all(1 == const_shp))
otype = GpuArrayType(dtype=v.dtype, broadcastable=bcast)
......@@ -481,4 +481,12 @@ class GpuAlloc(Op):
def grad(self, input, grads):
return [None for i in inputs]
def do_constant_folding(self, node):
if not getattr(node.ouputs[0], 'clients', []):
return False
for client in node.outputs[0].clients:
if client[0] == 'output':
return False
return True
gpu_alloc = GpuAlloc()
import unittest
from itertools import izip
from copy import copy, deepcopy
from nose.plugins.skip import SkipTest
import numpy
import theano
import theano.tensor as T
from theano.tensor.tests.test_basic import safe_make_node
import theano.sandbox.gpuarray
if theano.sandbox.gpuarray.pygpu is None:
raise SkipTest("pygpu disabled")
from theano.sandbox.gpuarray.type import GpuArrayType
from theano.sandbox.gpuarray.basic_ops import (host_from_gpu, gpu_from_host)
from theano.sandbox.gpuarray.type import GpuArrayType, \
gpuarray_shared_constructor
from theano.sandbox.gpuarray.basic_ops import host_from_gpu, gpu_from_host, \
gpu_alloc
from theano.tests import unittest_tools as utt
utt.seed_rng()
from pygpu import gpuarray
def rand_gpuarray(shape, dtype):
return gpuarray.array(numpy.random.rand(*shape), dtype=dtype)
if theano.config.mode == 'FAST_COMPILE':
mode_with_gpu = theano.compile.mode.get_mode('FAST_RUN').including('gpuarray')
mode_without_gpu = theano.compile.mode.get_mode('FAST_RUN').excluding('gpuarray'\
)
else:
mode_with_gpu = theano.compile.mode.get_default_mode().including('gpuarray')
mode_without_gpu = theano.compile.mode.get_default_mode().excluding('gpuarray')
def inplace_func(inputs, outputs, mode=None, allow_input_downcast=False,
on_unused_input='raise', name=None):
if mode is None:
mode = mode_with_gpu
return theano.function(inputs, outputs, mode=mode,
allow_input_downcast=allow_input_downcast,
accept_inplace=True,
on_unused_input=on_unused_input, name=name)
def fake_shared(value, name=None, strict=False, allow_downcast=None, **kwargs):
from theano.tensor.sharedvar import tensor_constructor, scalar_constructor
for c in (gpuarray_shared_constructor, tensor_constructor,
scalar_constructor):
try:
return c(value, name=name, strict=strict,
allow_downcast=allow_downcast, **kwargs)
except TypeError:
continue
def rand_gpuarray(*shape):
r = numpy.random.rand(*shape) * 2 - 1
return gpuarray.array(r, dtype=theano.config.floatX)
def makeTester(name, op, expected, good=None, bad_build=None, checks=None,
bad_runtime=None, mode=None, skip=False, eps=1e-10):
if good is None:
good = {}
if bad_build is None:
bad_build = {}
if bad_runtime is None:
bad_runtime = {}
if checks is None:
checks = {}
_op = op
_expected = expected
_good = good
_bad_build = bad_build
_bad_runtime = bad_runtime
_skip = skip
_checks = checks
class Checker(unittest.TestCase):
op = staticmethod(_op)
expected = staticmethod(_expected)
good = _good
bad_build = _bad_build
bad_runtime = _bad_runtime
skip = _skip
checks = _checks
def setUp(self):
eval(self.__class__.__module__ + '.' + self.__class__.__name__)
def test_good(self):
if skip:
raise SkipTest(skip)
for testname, inputs in good.items():
inputs = [copy(input) for input in inputs]
inputrs = [fake_shared(input) for input in inputs]
try:
node = safe_make_node(self.op, *inputrs)
except Exception, exc:
err_msg = ("Test %s::%s: Error occured while making "
"a node with inputs %s") % (self.op, testname,
inputs)
exc.args += (err_msg,)
raise
try:
f = inplace_func([], node.outputs, mode=mode,
name='test_good')
except Exception, exc:
err_msg = ("Test %s::%s: Error occured while trying to "
"make a Function") % (self.op, testname)
exc.args += (err_msg,)
raise
if isinstance(self.expected, dict) and \
testname in self.expected:
expecteds = self.expected[testname]
else:
expecteds = self.expected(*inputs)
if not isinstance(expecteds, (list, tuple)):
expecteds = (expecteds,)
try:
variables = f()
except Exception, exc:
err_msg = ("Test %s::%s: Error occured while calling "
"the Function on the inputs %s") % (self.op,
testname,
inputs)
exc.args += (err_msg,)
raise
for i, (variable, expected) in \
enumerate(izip(variables, expecteds)):
if variable.dtype != expected.dtype or \
variable.shape != expected.shape or \
not GpuArrayType.values_eq_approx(variable,
expected):
self.fail(("Test %s::%s: Output %s gave the wrong "
"value. With inputs %s, expected %s "
"(dtype %s), got %s (dtype %s).") % (
self.op, testname, i, inputs, expected,
expected.dtype, variable, variable.dtype))
def test_transfer():
for description, check in self.checks.items():
if not check(inputs, variables):
self.fail(("Test %s::%s: Failed check: %s "
"(inputs were %s, ouputs were %s)") %
(self.op, testname, description,
inputs, variables))
def test_bad_build(self):
if skip:
raise SkipTest(skip)
for testname, inputs in self.bad_build.items():
inputs = [copy(input) for input in inputs]
inputrs = [fake_shared(input) for input in inputs]
self.assertRaises(Exception, safe_make_node, self.op, *inputrs)
def test_bad_runtime(self):
if skip:
raise SkipTest(skip)
for testname, inputs in self.bad_runtime.items():
inputrs = [fake_shared(input) for input in inputs]
try:
node = safe_make_node(self.op, *inputrs)
except Exception, exc:
err_msg = ("Test %s::%s: Error occured while trying to "
"make a node with inputs %s") % (self.op,
testname,
inputs)
exc.args += (err_msg,)
raise
try:
f = inplace_func([], node.outputs, mode=mode,
name="test_bad_runtime")
except Exception, exc:
err_msg = ("Test %s::%s: Error occured while trying to "
"make a Function") % (self.op, testname)
exc.args += (err_msg,)
raise
self.assertRaises(Exception, f, [])
Checker.__name__ = name
return Checker
def test_transfer_cpu_gpu():
a = T.fmatrix('a')
g = GpuArrayType(dtype='float32', broadcastable=(False, False))('g')
......@@ -29,3 +203,48 @@ def test_transfer():
f = theano.function([g], host_from_gpu(g))
fv = f(gv)
assert numpy.allclose(fv, av)
def test_transfer_cuda_gpu():
import theano.sandbox.cuda as cuda_ndarray
if cuda_ndarray.cuda_available == False:
raise SkipTest("Can't test interaction with cuda if cuda not present")
g = GpuArrayType(dtype='float32', broadcastable=(False, False))('g')
c = cuda_ndarray.CudaNdarrayType((False, False))('c')
av = theano._asarray(numpy.random.rand(5, 4), dtype='float32')
gv = gpuarray.array(av)
cv = cuda_ndarray.CudaNdarray(av)
f = theano.function([c], gpu_from_cuda(c))
fv = f(cv)
assert GpuArrayType.values_eq_approx(fv, gv)
f = theano.function([g], cuda_from_gpu(g))
fv = f(gv)
assert cuda_ndarray.CudaNdarrayType.values_eq_approx(fv, cv)
def gpu_alloc_expected(x, *shp):
g = gpuarray.empty(shp, dtype=x.dtype)
g[:] = x
return g
GpuAllocTester = makeTester(
name="GpuAllocTester",
op=gpu_alloc,
expected=gpu_alloc_expected,
good=dict(
correct01=(rand_gpuarray(), numpy.int32(7)),
correct01_bcast=(rand_gpuarray(1), numpy.int32(7)),
correct02=(rand_gpuarray(), numpy.int32(4), numpy.int32(7)),
correct12=(rand_gpuarray(7), numpy.int32(4), numpy.int32(7)),
correct13=(rand_gpuarray(7), numpy.int32(2), numpy.int32(4),
numpy.int32(7)),
correct23=(rand_gpuarray(4, 7), numpy.int32(2), numpy.int32(4),
numpy.int32(7))
),
bad_runtime=dict(
bad_shape12=(rand_gpuarray(7), numpy.int32(7), numpy.int32(5)),
)
)
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论