提交 d0d64720 authored 作者: Reyhane Askari's avatar Reyhane Askari

removed centralized caching with metaclass (to keep it as history)

上级 63306840
from __future__ import absolute_import, print_function, division
import theano
from theano.gof.utils import CacheClass
from theano.gof.utils import (
give_variables_names, remove, unique)
......@@ -62,17 +61,3 @@ def test_stack_trace():
assert len(v.tag.trace[0]) == 2
finally:
theano.config.traceback.limit = orig
class CachingClassExample(CacheClass, theano.Op):
__props__ = ('value',)
__cache_instance__ = True
def __init__(self, value):
self.value = value
def test_caching():
obj_1 = CachingClassExample(3)
obj_2 = CachingClassExample(3)
assert obj_1 is obj_2
......@@ -386,6 +386,9 @@ if run_memory_usage_tests:
class RunOnce(theano.Op):
__props__ = ("nb_run",)
def __init__(self):
self.nb_run = 0
......
......@@ -9,7 +9,6 @@ from six.moves import StringIO
from theano import config
from theano.compat import PY3
from theano.misc.frozendict import frozendict
def simple_extract_stack(f=None, limit=None, skips=[]):
......@@ -212,49 +211,6 @@ class MetaObject(type):
return type.__new__(cls, name, bases, dct)
class MetaObject_caching(MetaObject):
_cache = {}
def __call__(cls, *args, **kwargs):
key = [cls]
for arg in args:
arg = make_hashable(arg)
key.append(arg)
for k, v in sorted(kwargs.items()):
key.append(k)
v = make_hashable(v)
key.append(v)
key = tuple(key)
if key not in cls._cache:
cls._cache[key] = super(MetaObject_caching, cls).__call__(*args, **kwargs)
return cls._cache[key]
class CacheClass(with_metaclass(MetaObject_caching, object)):
pass
def make_hashable(argument):
try:
hash(argument)
return argument
except:
if isinstance(argument, (list, tuple)):
argument = list(argument)
for index, instance in enumerate(argument):
argument[index] = make_hashable(instance)
argument = tuple(argument)
elif isinstance(argument, dict):
for k, v in argument.items():
argument[k] = make_hashable(v)
argument = frozendict(argument)
elif isinstance(argument, slice):
argument = argument.__reduce__()
elif isinstance(argument, np.ndarray):
argument = hash_from_ndarray(argument)
return argument
class object2(with_metaclass(MetaObject, object)):
__slots__ = []
......@@ -609,30 +565,6 @@ else:
return hashlib.md5(np.getbuffer(msg)).hexdigest()
def hash_from_ndarray(data):
"""
Return a hash from an ndarray.
It takes care of the data, shapes, strides and dtype.
"""
# We need to hash the shapes and strides as hash_from_code only hashes
# the data buffer. Otherwise, this will cause problem with shapes like:
# (1, 0) and (2, 0) and problem with inplace transpose.
# We also need to add the dtype to make the distinction between
# uint32 and int32 of zeros with the same shape and strides.
# python hash are not strong, so I always use md5 in order not to have a
# too long hash, I call it again on the concatenation of all parts.
if not data.flags["C_CONTIGUOUS"]:
# hash_from_code needs a C-contiguous array.
data = np.ascontiguousarray(data)
return hash_from_code(hash_from_code(data) +
hash_from_code(str(data.shape)) +
hash_from_code(str(data.strides)) +
hash_from_code(str(data.dtype)))
def hash_from_file(file_path):
"""
Return the MD5 hash of a file.
......
......@@ -12,7 +12,7 @@ from theano.tensor.basic import (
Alloc, AllocEmpty, alloc_validate_shape, Join, Split)
from theano.gof import HideC, COp
from theano.gof.utils import MethodNotDefined, CacheClass
from theano.gof.utils import MethodNotDefined
from collections import deque
......@@ -629,7 +629,7 @@ class HostFromGpu(Op):
host_from_gpu = HostFromGpu()
class GpuFromHost(CacheClass, Op):
class GpuFromHost(Op):
"""
Transfer data to GPU.
......@@ -783,7 +783,7 @@ class GpuToGpu(Op):
return (1,)
class GpuAlloc(CacheClass, HideC, Alloc):
class GpuAlloc(HideC, Alloc):
"""
Allocate initialized memory on the GPU.
......@@ -945,7 +945,7 @@ class GpuAlloc(CacheClass, HideC, Alloc):
return True
class GpuAllocEmpty(CacheClass, HideC, AllocEmpty):
class GpuAllocEmpty(HideC, AllocEmpty):
"""
Allocate uninitialized memory on the GPU.
......
......@@ -13,7 +13,6 @@ from theano.scalar import as_scalar, constant, Log, get_scalar_type
from theano.tensor import as_tensor_variable
from theano.gradient import DisconnectedType, grad_not_implemented
from theano.gof import Optimizer, local_optimizer, COp
from theano.gof.utils import CacheClass
from theano.gof.cmodule import GCC_compiler
from theano.gof.type import CDataType, Generic
from theano.compile import optdb
......@@ -349,7 +348,7 @@ def version(raises=True):
version.v = None
class GpuDnnConvDesc(CacheClass, COp):
class GpuDnnConvDesc(COp):
"""
This Op builds a convolution descriptor for use in the other convolution
......@@ -640,7 +639,7 @@ class GpuDnnConv(DnnBase):
return [shape[2]]
class GpuDnnConvGradW(CacheClass, DnnBase):
class GpuDnnConvGradW(DnnBase):
"""
The convolution gradient with respect to the weights.
......@@ -771,7 +770,7 @@ class GpuDnnConvGradW(CacheClass, DnnBase):
return [shape[2]]
class GpuDnnConvGradI(CacheClass, DnnBase):
class GpuDnnConvGradI(DnnBase):
"""
The convolution gradient with respect to the inputs.
......@@ -1138,8 +1137,9 @@ def dnn_gradweight(img, topgrad, kerns_shp, border_mode='valid',
precision = get_precision(precision, [img, topgrad])
desc = GpuDnnConvDesc(border_mode=border_mode, subsample=subsample,
conv_mode=conv_mode, precision=precision)(kerns_shp)
out = GpuAllocEmpty(dtype=img.dtype, context_name=ctx_name)(*kerns_shp)
conv_mode=conv_mode, precision=precision)(
kerns_shp)
out = GpuAllocEmpty(ctx_name, dtype=img.dtype)(*kerns_shp)
return GpuDnnConvGradW()(img, topgrad, out, desc)
......@@ -1151,7 +1151,6 @@ def dnn_gradweight3d(img, topgrad, kerns_shp, border_mode='valid',
return dnn_gradweight(img, topgrad, kerns_shp, border_mode,
subsample, conv_mode, precision)
def dnn_gradinput(kerns, topgrad, img_shp, border_mode='valid',
subsample=(1, 1), conv_mode='conv', precision=None):
"""
......@@ -1166,8 +1165,9 @@ def dnn_gradinput(kerns, topgrad, img_shp, border_mode='valid',
precision = get_precision(precision, [kerns, topgrad])
desc = GpuDnnConvDesc(border_mode=border_mode, subsample=subsample,
conv_mode=conv_mode, precision=precision)(kerns.shape)
out = GpuAllocEmpty(dtype=kerns.dtype, context_name=ctx_name)(*img_shp)
conv_mode=conv_mode, precision=precision)(
kerns.shape)
out = GpuAllocEmpty(ctx_name, kerns.dtype)(*img_shp)
return GpuDnnConvGradI()(kerns, topgrad, out, desc)
......@@ -1179,7 +1179,6 @@ def dnn_gradinput3d(kerns, topgrad, img_shp, border_mode='valid',
return dnn_gradinput(kerns, topgrad, img_shp, border_mode, subsample,
conv_mode, precision)
class GpuDnnPoolDesc(Op):
"""
......
......@@ -346,7 +346,6 @@ class InplaceElemwiseOptimizer(Optimizer):
inplace_pattern = dict(baseline)
inplace_pattern[candidate_output] = candidate_input
inplace_pattern = theano.misc.frozendict.frozendict(inplace_pattern)
try:
if hasattr(op.scalar_op, "make_new_inplace"):
new_scal = op.scalar_op.make_new_inplace(
......@@ -7271,14 +7270,7 @@ your code will run correctly, but may be slower.""")
# Do not call make_node to have test_value
n = maker(node, C)(*inputs).owner
assert len(n.outputs) == 1
assert node.outputs[0].dtype == n.outputs[0].dtype, (
"node.outputs[0].dtype: %r" % node.outputs[0].dtype,
"n.outputs[0].dtype: %r" % n.outputs[0].dtype,
"n.op: %r" % n.op, "node.op: %r" % node.op,
"n.outputs %r" % n.outputs, "n: %r" % n,
"node.outputs %r" % node.outputs, "node %r" % node,
"inputs: %r" % n.inputs, "s_inputs: %r" % s_inputs,
"s_new_out: %r" % s_new_out, "OP: %r" % OP)
assert node.outputs[0].dtype == n.outputs[0].dtype
if len(n.inputs) > max_nb_input:
_logger.info('loop fusion failed because Op would exceed'
......
......@@ -4,8 +4,8 @@ import unittest
import numpy
import theano
from theano.tensor.utils import shape_of_variables
from theano.gof.utils import hash_from_ndarray
from theano.tensor.utils import (hash_from_ndarray, shape_of_variables)
def test_hash_from_ndarray():
hashs = []
......
from __future__ import absolute_import, print_function, division
import numpy
import theano
from theano.compat import izip
from theano.gof.utils import hash_from_code
def hash_from_ndarray(data):
"""
Return a hash from an ndarray.
It takes care of the data, shapes, strides and dtype.
"""
# We need to hash the shapes and strides as hash_from_code only hashes
# the data buffer. Otherwise, this will cause problem with shapes like:
# (1, 0) and (2, 0) and problem with inplace transpose.
# We also need to add the dtype to make the distinction between
# uint32 and int32 of zeros with the same shape and strides.
# python hash are not strong, so I always use md5 in order not to have a
# too long hash, I call it again on the concatenation of all parts.
if not data.flags["C_CONTIGUOUS"]:
# hash_from_code needs a C-contiguous array.
data = numpy.ascontiguousarray(data)
return hash_from_code(hash_from_code(data) +
hash_from_code(str(data.shape)) +
hash_from_code(str(data.strides)) +
hash_from_code(str(data.dtype)))
def shape_of_variables(fgraph, input_shapes):
......
......@@ -12,7 +12,8 @@ import theano
from theano.compat import PY3
from theano.scalar import ComplexError, IntegerDivisionError
from theano.gof import Constant, Variable
from theano.gof.utils import hashtype, hash_from_ndarray
from theano.gof.utils import hashtype
from theano.tensor.utils import hash_from_ndarray
from theano.tensor.type import TensorType
from theano.configparser import config
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论