提交 8da054b7 authored 作者: abergeron's avatar abergeron

Merge pull request #1994 from nouiz/lazy

[CRASH] fix tutorial example related to lazy evaluation.
...@@ -211,18 +211,18 @@ version that it produces in the code I gave above. ...@@ -211,18 +211,18 @@ version that it produces in the code I gave above.
return self.ccode % locals() return self.ccode % locals()
add = BinaryDoubleOp(name = 'add', add = BinaryDoubleOp(name='add',
fn = lambda x, y: x + y, fn=lambda x, y: x + y,
ccode = "%(z)s = %(x)s + %(y)s;") ccode="%(z)s = %(x)s + %(y)s;")
sub = BinaryDoubleOp(name = 'sub', sub = BinaryDoubleOp(name='sub',
fn = lambda x, y: x - y, fn=lambda x, y: x - y,
ccode = "%(z)s = %(x)s - %(y)s;") ccode="%(z)s = %(x)s - %(y)s;")
mul = BinaryDoubleOp(name = 'mul', mul = BinaryDoubleOp(name='mul',
fn = lambda x, y: x * y, fn=lambda x, y: x * y,
ccode = "%(z)s = %(x)s * %(y)s;") ccode="%(z)s = %(x)s * %(y)s;")
div = BinaryDoubleOp(name = 'div', div = BinaryDoubleOp(name='div',
fn = lambda x, y: x / y, fn=lambda x, y: x / y,
ccode = "%(z)s = %(x)s / %(y)s;") ccode="%(z)s = %(x)s / %(y)s;")
...@@ -633,17 +633,17 @@ arithmetic operators: ...@@ -633,17 +633,17 @@ arithmetic operators:
def __str__(self): def __str__(self):
return self.name return self.name
add = BinaryDoubleOp(name = 'add', add = BinaryDoubleOp(name='add',
fn = lambda x, y: x + y) fn=lambda x, y: x + y)
sub = BinaryDoubleOp(name = 'sub', sub = BinaryDoubleOp(name='sub',
fn = lambda x, y: x - y) fn=lambda x, y: x - y)
mul = BinaryDoubleOp(name = 'mul', mul = BinaryDoubleOp(name='mul',
fn = lambda x, y: x * y) fn=lambda x, y: x * y)
div = BinaryDoubleOp(name = 'div', div = BinaryDoubleOp(name='div',
fn = lambda x, y: x / y) fn=lambda x, y: x / y)
Instead of working directly on an instance of Op, we create a subclass of Instead of working directly on an instance of Op, we create a subclass of
Op that we can parametrize. All the operations we define are binary. They Op that we can parametrize. All the operations we define are binary. They
......
...@@ -685,15 +685,19 @@ Modify and execute to work for a matrix of shape (20, 10). ...@@ -685,15 +685,19 @@ Modify and execute to work for a matrix of shape (20, 10).
class PyCUDADoubleOp(theano.Op): class PyCUDADoubleOp(theano.Op):
def __eq__(self, other): def __eq__(self, other):
return type(self) == type(other) return type(self) == type(other)
def __hash__(self): def __hash__(self):
return hash(type(self)) return hash(type(self))
def __str__(self): def __str__(self):
return self.__class__.__name__ return self.__class__.__name__
def make_node(self, inp): def make_node(self, inp):
inp = cuda.basic_ops.gpu_contiguous( inp = cuda.basic_ops.gpu_contiguous(
cuda.basic_ops.as_cuda_ndarray_variable(inp)) cuda.basic_ops.as_cuda_ndarray_variable(inp))
assert inp.dtype == "float32" assert inp.dtype == "float32"
return theano.Apply(self, [inp], [inp.type()]) return theano.Apply(self, [inp], [inp.type()])
def make_thunk(self, node, storage_map, _, _2): def make_thunk(self, node, storage_map, _, _2):
mod = SourceModule(""" mod = SourceModule("""
__global__ void my_fct(float * i0, float * o0, int size) { __global__ void my_fct(float * i0, float * o0, int size) {
...@@ -703,15 +707,16 @@ Modify and execute to work for a matrix of shape (20, 10). ...@@ -703,15 +707,16 @@ Modify and execute to work for a matrix of shape (20, 10).
} }
}""") }""")
pycuda_fct = mod.get_function("my_fct") pycuda_fct = mod.get_function("my_fct")
inputs = [ storage_map[v] for v in node.inputs] inputs = [storage_map[v] for v in node.inputs]
outputs = [ storage_map[v] for v in node.outputs] outputs = [storage_map[v] for v in node.outputs]
def thunk(): def thunk():
z = outputs[0] z = outputs[0]
if z[0] is None or z[0].shape!=inputs[0][0].shape: if z[0] is None or z[0].shape != inputs[0][0].shape:
z[0] = cuda.CudaNdarray.zeros(inputs[0][0].shape) z[0] = cuda.CudaNdarray.zeros(inputs[0][0].shape)
grid = (int(numpy.ceil(inputs[0][0].size / 512.)),1) grid = (int(numpy.ceil(inputs[0][0].size / 512.)), 1)
pycuda_fct(inputs[0][0], z[0], numpy.intc(inputs[0][0].size), pycuda_fct(inputs[0][0], z[0], numpy.intc(inputs[0][0].size),
block=(512,1,1), grid=grid) block=(512, 1, 1), grid=grid)
return thunk return thunk
...@@ -719,7 +724,7 @@ Use this code to test it: ...@@ -719,7 +724,7 @@ Use this code to test it:
>>> x = theano.tensor.fmatrix() >>> x = theano.tensor.fmatrix()
>>> f = theano.function([x], PyCUDADoubleOp()(x)) >>> f = theano.function([x], PyCUDADoubleOp()(x))
>>> xv=numpy.ones((4,5), dtype="float32") >>> xv = numpy.ones((4, 5), dtype="float32")
>>> assert numpy.allclose(f(xv), xv*2) >>> assert numpy.allclose(f(xv), xv*2)
>>> print numpy.asarray(f(xv)) >>> print numpy.asarray(f(xv))
......
...@@ -886,6 +886,11 @@ class VM_Linker(link.LocalLinker): ...@@ -886,6 +886,11 @@ class VM_Linker(link.LocalLinker):
storage_map, storage_map,
compute_map, compute_map,
no_recycling)) no_recycling))
if not hasattr(thunks[-1], 'lazy'):
# We don't want all ops maker to think about lazy Ops.
# So if they didn't specify that its lazy or not, it isn't.
# If this member isn't present, it will crash later.
thunks[-1].lazy = False
except Exception, e: except Exception, e:
e.args = ("The following error happened while" e.args = ("The following error happened while"
" compiling the node", node, "\n") + e.args " compiling the node", node, "\n") + e.args
......
...@@ -9,7 +9,7 @@ if not theano.misc.pycuda_init.pycuda_available: ...@@ -9,7 +9,7 @@ if not theano.misc.pycuda_init.pycuda_available:
" with pycuda code.") " with pycuda code.")
import theano.sandbox.cuda as cuda_ndarray import theano.sandbox.cuda as cuda_ndarray
if cuda_ndarray.cuda_available == False: if not cuda_ndarray.cuda_available:
from nose.plugins.skip import SkipTest from nose.plugins.skip import SkipTest
raise SkipTest('Optional package cuda disabled') raise SkipTest('Optional package cuda disabled')
......
""" test code snippet in the Theano tutorials. """ test code snippet in the Theano tutorials.
""" """
import os, shutil, unittest import os
import shutil
import unittest
from nose.plugins.skip import SkipTest
import numpy
from numpy import array
import theano import theano
import theano.tensor as T import theano.tensor as T
from theano import function from theano import function
import numpy
from numpy import array
from theano import config from theano import config
from theano.tests import unittest_tools as utt from theano.tests import unittest_tools as utt
...@@ -15,13 +20,13 @@ from theano.tensor.shared_randomstreams import RandomStreams ...@@ -15,13 +20,13 @@ from theano.tensor.shared_randomstreams import RandomStreams
class T_extending(unittest.TestCase): class T_extending(unittest.TestCase):
## All tests here belong to files in # All tests here belong to files in
## http://deeplearning.net/software/theano/extending # http://deeplearning.net/software/theano/extending
## Theano/doc/extending/*.txt # Theano/doc/extending/*.txt
## Any change you do here also add it to the tutorial! # Any change you do here also add it to the tutorial!
## This belongs to an entire folder since code-snippets are connected # This belongs to an entire folder since code-snippets are connected
## from one file to another .. and they do not make sense on their # from one file to another .. and they do not make sense on their
## own. # own.
def test_extending_1(self): def test_extending_1(self):
...@@ -103,8 +108,8 @@ class T_extending(unittest.TestCase): ...@@ -103,8 +108,8 @@ class T_extending(unittest.TestCase):
x, y = double('x'), double('y') x, y = double('x'), double('y')
z = mul(x, y) z = mul(x, y)
f = theano.function([x, y], z) f = theano.function([x, y], z)
assert f(5, 6) == 30.0 assert f(5, 6) == 30.0
assert f(5.6, 6.7) == 37.519999999999996 assert f(5.6, 6.7) == 37.519999999999996
x = double('x') x = double('x')
self.assertRaises(AttributeError, mul, x, 2) self.assertRaises(AttributeError, mul, x, 2)
...@@ -156,18 +161,17 @@ class T_extending(unittest.TestCase): ...@@ -156,18 +161,17 @@ class T_extending(unittest.TestCase):
def __str__(self): def __str__(self):
return self.name return self.name
add = BinaryDoubleOp(name = 'add', add = BinaryDoubleOp(name='add',
fn = lambda x, y: x + y) fn=lambda x, y: x + y)
sub = BinaryDoubleOp(name = 'sub', sub = BinaryDoubleOp(name='sub',
fn = lambda x, y: x - y) fn=lambda x, y: x - y)
mul = BinaryDoubleOp(name = 'mul', mul = BinaryDoubleOp(name='mul',
fn = lambda x, y: x * y) fn=lambda x, y: x * y)
div = BinaryDoubleOp(name = 'div',
fn = lambda x, y: x / y)
div = BinaryDoubleOp(name='div',
fn=lambda x, y: x / y)
def test_extending_2(self): def test_extending_2(self):
''' '''
...@@ -220,22 +224,22 @@ class T_extending(unittest.TestCase): ...@@ -220,22 +224,22 @@ class T_extending(unittest.TestCase):
def __str__(self): def __str__(self):
return self.name return self.name
add = BinaryDoubleOp(name = 'add', add = BinaryDoubleOp(name='add',
fn = lambda x, y: x + y) fn=lambda x, y: x + y)
sub = BinaryDoubleOp(name = 'sub', sub = BinaryDoubleOp(name='sub',
fn = lambda x, y: x - y) fn=lambda x, y: x - y)
mul = BinaryDoubleOp(name = 'mul', mul = BinaryDoubleOp(name='mul',
fn = lambda x, y: x * y) fn=lambda x, y: x * y)
div = BinaryDoubleOp(name = 'div', div = BinaryDoubleOp(name='div',
fn = lambda x, y: x / y) fn=lambda x, y: x / y)
def c_declare(name, sub, check_input=True): def c_declare(name, sub, check_input=True):
return """ return """
double %(name)s; double %(name)s;
""" % dict(name = name) """ % dict(name=name)
double.c_declare = c_declare double.c_declare = c_declare
...@@ -380,21 +384,21 @@ class T_extending(unittest.TestCase): ...@@ -380,21 +384,21 @@ class T_extending(unittest.TestCase):
return self.ccode % locals() return self.ccode % locals()
add = BinaryDoubleOp(name = 'add', add = BinaryDoubleOp(name='add',
fn = lambda x, y: x + y, fn=lambda x, y: x + y,
ccode = "%(z)s = %(x)s + %(y)s;") ccode="%(z)s = %(x)s + %(y)s;")
sub = BinaryDoubleOp(name = 'sub', sub = BinaryDoubleOp(name='sub',
fn = lambda x, y: x - y, fn=lambda x, y: x - y,
ccode = "%(z)s = %(x)s - %(y)s;") ccode="%(z)s = %(x)s - %(y)s;")
mul = BinaryDoubleOp(name = 'mul', mul = BinaryDoubleOp(name='mul',
fn = lambda x, y: x * y, fn=lambda x, y: x * y,
ccode = "%(z)s = %(x)s * %(y)s;") ccode="%(z)s = %(x)s * %(y)s;")
div = BinaryDoubleOp(name = 'div', div = BinaryDoubleOp(name='div',
fn = lambda x, y: x / y, fn=lambda x, y: x / y,
ccode = "%(z)s = %(x)s / %(y)s;") ccode="%(z)s = %(x)s / %(y)s;")
from theano.gof import toolbox from theano.gof import toolbox
...@@ -452,10 +456,10 @@ class T_extending(unittest.TestCase): ...@@ -452,10 +456,10 @@ class T_extending(unittest.TestCase):
class T_introduction(unittest.TestCase): class T_introduction(unittest.TestCase):
## All tests here belong to # All tests here belong to
## http://deeplearning.net/software/theano/tutorial/introduction.html # http://deeplearning.net/software/theano/tutorial/introduction.html
## Theano/doc/tutorial/introduction.txt # Theano/doc/tutorial/introduction.txt
## Any change you do here also add it to the tutorial ! # Any change you do here also add it to the tutorial !
def test_introduction_1(self): def test_introduction_1(self):
import theano import theano
...@@ -477,10 +481,10 @@ class T_introduction(unittest.TestCase): ...@@ -477,10 +481,10 @@ class T_introduction(unittest.TestCase):
class T_adding(unittest.TestCase): class T_adding(unittest.TestCase):
## All tests here belong to # All tests here belong to
## http://deeplearning.net/software/theano/tutorial/adding.html # http://deeplearning.net/software/theano/tutorial/adding.html
## Theano/doc/tutorial/adding.txt # Theano/doc/tutorial/adding.txt
## Any change you do here also add it to the tutorial ! # Any change you do here also add it to the tutorial !
def test_adding_1(self): def test_adding_1(self):
...@@ -508,10 +512,10 @@ class T_adding(unittest.TestCase): ...@@ -508,10 +512,10 @@ class T_adding(unittest.TestCase):
class T_examples(unittest.TestCase): class T_examples(unittest.TestCase):
## All tests here belog to # All tests here belog to
## http://deeplearning.net/software/theano/tutorial/examples.html # http://deeplearning.net/software/theano/tutorial/examples.html
## Theano/doc/tutorial/examples.txt # Theano/doc/tutorial/examples.txt
## Any change you do here also add it to the tutorial ! # Any change you do here also add it to the tutorial !
def test_examples_1(self): def test_examples_1(self):
x = T.dmatrix('x') x = T.dmatrix('x')
...@@ -747,10 +751,10 @@ class T_examples(unittest.TestCase): ...@@ -747,10 +751,10 @@ class T_examples(unittest.TestCase):
class T_aliasing(unittest.TestCase): class T_aliasing(unittest.TestCase):
## All tests here belog to # All tests here belog to
## http://deeplearning.net/software/theano/tutorial/aliasing.html # http://deeplearning.net/software/theano/tutorial/aliasing.html
## Theano/doc/tutorial/aliasing.txt # Theano/doc/tutorial/aliasing.txt
## Any change you do here also add it to the tutorial ! # Any change you do here also add it to the tutorial !
def test_aliasing_1(self): def test_aliasing_1(self):
...@@ -782,7 +786,7 @@ class T_aliasing(unittest.TestCase): ...@@ -782,7 +786,7 @@ class T_aliasing(unittest.TestCase):
s.set_value( s.set_value(
## some_inplace_fn # some_inplace_fn
s.get_value(borrow=True).__imul__(2), s.get_value(borrow=True).__imul__(2),
borrow=True) borrow=True)
...@@ -797,12 +801,11 @@ class T_aliasing(unittest.TestCase): ...@@ -797,12 +801,11 @@ class T_aliasing(unittest.TestCase):
f = theano.function([theano.In(x, borrow=True)], theano.Out(y, borrow=True)) f = theano.function([theano.In(x, borrow=True)], theano.Out(y, borrow=True))
class T_loading_and_saving(unittest.TestCase): class T_loading_and_saving(unittest.TestCase):
## All tests here belong to # All tests here belong to
## http://deeplearning.net/software/theano/tutorial/loading_and_saving.html # http://deeplearning.net/software/theano/tutorial/loading_and_saving.html
## Theano/doc/tutorial/loading_and_saving.txt # Theano/doc/tutorial/loading_and_saving.txt
## Any change you do here also add it to the tutorial ! # Any change you do here also add it to the tutorial !
def test_loading_and_saving_1(self): def test_loading_and_saving_1(self):
...@@ -855,11 +858,12 @@ class T_loading_and_saving(unittest.TestCase): ...@@ -855,11 +858,12 @@ class T_loading_and_saving(unittest.TestCase):
if tmpdir is not None: if tmpdir is not None:
shutil.rmtree(tmpdir) shutil.rmtree(tmpdir)
class T_modes(unittest.TestCase): class T_modes(unittest.TestCase):
## All tests here belog to # All tests here belog to
## http://deeplearning.net/software/theano/tutorial/modes.html # http://deeplearning.net/software/theano/tutorial/modes.html
## Theano/doc/tutorial/modes.txt # Theano/doc/tutorial/modes.txt
## Any change you do here also add it to the tutorial ! # Any change you do here also add it to the tutorial !
def test_modes_1(self): def test_modes_1(self):
...@@ -868,15 +872,15 @@ class T_modes(unittest.TestCase): ...@@ -868,15 +872,15 @@ class T_modes(unittest.TestCase):
f = theano.function([x], 10*x, mode='DEBUG_MODE') f = theano.function([x], 10*x, mode='DEBUG_MODE')
assert numpy.all(f([5]) == [50.]) assert numpy.all(f([5]) == [50.])
assert numpy.all(f([0]) == [0.] ) assert numpy.all(f([0]) == [0.])
assert numpy.all(f([7]) == [70.]) assert numpy.all(f([7]) == [70.])
class T_using_gpu(unittest.TestCase):
## All tests here belog to
## http://deeplearning.net/software/theano/tutorial/using_gpu.html
## Theano/doc/tutorial/using_gpu.txt
## Any change you do here also add it to the tutorial !
class T_using_gpu(unittest.TestCase):
# All tests here belog to
# http://deeplearning.net/software/theano/tutorial/using_gpu.html
# Theano/doc/tutorial/using_gpu.txt
# Any change you do here also add it to the tutorial !
def test_using_gpu_1(self): def test_using_gpu_1(self):
# I'm checking if this compiles and runs # I'm checking if this compiles and runs
...@@ -907,9 +911,7 @@ class T_using_gpu(unittest.TestCase): ...@@ -907,9 +911,7 @@ class T_using_gpu(unittest.TestCase):
else: else:
assert numpy.any([isinstance(x.op, T.Elemwise) for x in f.maker.fgraph.toposort()]) assert numpy.any([isinstance(x.op, T.Elemwise) for x in f.maker.fgraph.toposort()])
def test_using_gpu_2(self): def test_using_gpu_2(self):
if theano.config.device.find('gpu') > -1: if theano.config.device.find('gpu') > -1:
from theano import function, config, shared, sandbox from theano import function, config, shared, sandbox
...@@ -972,6 +974,61 @@ class T_using_gpu(unittest.TestCase): ...@@ -972,6 +974,61 @@ class T_using_gpu(unittest.TestCase):
assert not numpy.any([isinstance(x.op, T.Elemwise) assert not numpy.any([isinstance(x.op, T.Elemwise)
for x in f.maker.fgraph.toposort()]) for x in f.maker.fgraph.toposort()])
def test_using_gpu_pycudaop(self):
import theano.misc.pycuda_init
if not theano.misc.pycuda_init.pycuda_available:
raise SkipTest("Pycuda not installed. Skip test of theano op"
" with pycuda code.")
from pycuda.compiler import SourceModule
import theano.sandbox.cuda as cuda
import theano.sandbox.cuda as cuda_ndarray
if not cuda_ndarray.cuda_available:
raise SkipTest('Optional package cuda disabled')
class PyCUDADoubleOp(theano.Op):
def __eq__(self, other):
return type(self) == type(other)
def __hash__(self):
return hash(type(self))
def __str__(self):
return self.__class__.__name__
def make_node(self, inp):
inp = cuda.basic_ops.gpu_contiguous(
cuda.basic_ops.as_cuda_ndarray_variable(inp))
assert inp.dtype == "float32"
return theano.Apply(self, [inp], [inp.type()])
def make_thunk(self, node, storage_map, _, _2):
mod = SourceModule("""
__global__ void my_fct(float * i0, float * o0, int size) {
int i = blockIdx.x*blockDim.x + threadIdx.x;
if(i<size){
o0[i] = i0[i]*2;
}
}""")
pycuda_fct = mod.get_function("my_fct")
inputs = [storage_map[v] for v in node.inputs]
outputs = [storage_map[v] for v in node.outputs]
def thunk():
z = outputs[0]
if z[0] is None or z[0].shape != inputs[0][0].shape:
z[0] = cuda.CudaNdarray.zeros(inputs[0][0].shape)
grid = (int(numpy.ceil(inputs[0][0].size / 512.)), 1)
pycuda_fct(inputs[0][0], z[0],
numpy.intc(inputs[0][0].size),
block=(512, 1, 1), grid=grid)
return thunk
x = theano.tensor.fmatrix()
f = theano.function([x], PyCUDADoubleOp()(x))
xv = numpy.ones((4, 5), dtype="float32")
assert numpy.allclose(f(xv), xv*2)
# print numpy.asarray(f(xv))
# Used in T_fibby # Used in T_fibby
class Fibby(theano.Op): class Fibby(theano.Op):
...@@ -1024,10 +1081,10 @@ class Fibby(theano.Op): ...@@ -1024,10 +1081,10 @@ class Fibby(theano.Op):
class T_fibby(unittest.TestCase): class T_fibby(unittest.TestCase):
## All tests here belong to # All tests here belong to
## http://deeplearning.net/software/theano/extending/fibby.html # http://deeplearning.net/software/theano/extending/fibby.html
## Theano/doc/extending/fibby.txt # Theano/doc/extending/fibby.txt
## Any change you do here also add it to the tutorial ! # Any change you do here also add it to the tutorial !
def test_fibby_1(self): def test_fibby_1(self):
...@@ -1080,10 +1137,10 @@ class T_fibby(unittest.TestCase): ...@@ -1080,10 +1137,10 @@ class T_fibby(unittest.TestCase):
class T_graphstructures(unittest.TestCase): class T_graphstructures(unittest.TestCase):
## All tests here belong to # All tests here belong to
## http://deeplearning.net/software/theano/extending/graphstructures.html # http://deeplearning.net/software/theano/extending/graphstructures.html
## Theano/doc/extending/graphstructures.txt # Theano/doc/extending/graphstructures.txt
## Any change you do here also add it to the tutorial ! # Any change you do here also add it to the tutorial !
def test_graphstructures_1(self): def test_graphstructures_1(self):
...@@ -1145,10 +1202,10 @@ class T_graphstructures(unittest.TestCase): ...@@ -1145,10 +1202,10 @@ class T_graphstructures(unittest.TestCase):
class T_scan(unittest.TestCase): class T_scan(unittest.TestCase):
## All tests here belong to # All tests here belong to
## http://deeplearning.net/software/theano/tutorial/loop.html # http://deeplearning.net/software/theano/tutorial/loop.html
## Theano/doc/tutorial/loop.txt # Theano/doc/tutorial/loop.txt
## Any change you do here also add it to the tutorial ! # Any change you do here also add it to the tutorial !
def test_elemwise(self): def test_elemwise(self):
# defining the tensor variables # defining the tensor variables
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论