提交 3704fc21 authored 作者: Olivier Delalleau's avatar Olivier Delalleau

Merged

...@@ -24,3 +24,5 @@ pull.sh ...@@ -24,3 +24,5 @@ pull.sh
setuptools-*.egg setuptools-*.egg
theano/version.py theano/version.py
theano/version.py.out theano/version.py.out
distribute-*.egg
distribute-*.tar.gz
Theano is a Python library that allows you to define, optimize, and efficiently evaluate mathematical expressions involving multi-dimensional arrays. It is built on top of NumPy_. Theano features:
* **tight integration with NumPy:** a similar interface to NumPy's. numpy.ndarrays are also used internally in Theano-compiled functions.
* **transparent use of a GPU:** perform data-intensive computations up to 140x faster than on a CPU (support for float32 only).
* **efficient symbolic differentiation:** Theano can compute derivatives for functions of one or many inputs.
* **speed and stability optimizations:** avoid nasty bugs when computing expressions such as log(1+ exp(x) ) for large values of x.
* **dynamic C code generation:** evaluate expressions faster.
* **extensive unit-testing and self-verification:** includes tools for detecting and diagnosing bugs and/or potential problems.
Theano has been powering large-scale computationally intensive scientific
research since 2007, but it is also approachable enough to be used in the
classroom (IFT6266 at the University of Montreal).
.. _NumPy: http://numpy.scipy.org/
...@@ -3,3 +3,4 @@ global-include *.cu ...@@ -3,3 +3,4 @@ global-include *.cu
global-include *.cuh global-include *.cuh
global-include *.sh global-include *.sh
include ChangeLog include ChangeLog
include distribute_setup.py
To install the package, see this page: To install the package, see this page:
http://deeplearning.net/software/theano/install.html#install http://deeplearning.net/software/theano/install.html
For the documentation, see the project website: For the documentation, see the project website:
......
#!python
"""Bootstrap distribute installation
If you want to use setuptools in your package's setup.py, just include this
file in the same directory with it, and add this to the top of your setup.py::
from distribute_setup import use_setuptools
use_setuptools()
If you want to require a specific version of setuptools, set a download
mirror, or use an alternate download directory, you can do so by supplying
the appropriate options to ``use_setuptools()``.
This file can also be run as a script to install or upgrade setuptools.
"""
import os
import sys
import time
import fnmatch
import tempfile
import tarfile
from distutils import log
try:
from site import USER_SITE
except ImportError:
USER_SITE = None
try:
import subprocess
def _python_cmd(*args):
args = (sys.executable,) + args
return subprocess.call(args) == 0
except ImportError:
# will be used for python 2.3
def _python_cmd(*args):
args = (sys.executable,) + args
# quoting arguments if windows
if sys.platform == 'win32':
def quote(arg):
if ' ' in arg:
return '"%s"' % arg
return arg
args = [quote(arg) for arg in args]
return os.spawnl(os.P_WAIT, sys.executable, *args) == 0
DEFAULT_VERSION = "0.6.14"
DEFAULT_URL = "http://pypi.python.org/packages/source/d/distribute/"
SETUPTOOLS_FAKED_VERSION = "0.6c11"
SETUPTOOLS_PKG_INFO = """\
Metadata-Version: 1.0
Name: setuptools
Version: %s
Summary: xxxx
Home-page: xxx
Author: xxx
Author-email: xxx
License: xxx
Description: xxx
""" % SETUPTOOLS_FAKED_VERSION
def _install(tarball):
# extracting the tarball
tmpdir = tempfile.mkdtemp()
log.warn('Extracting in %s', tmpdir)
old_wd = os.getcwd()
try:
os.chdir(tmpdir)
tar = tarfile.open(tarball)
_extractall(tar)
tar.close()
# going in the directory
subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
os.chdir(subdir)
log.warn('Now working in %s', subdir)
# installing
log.warn('Installing Distribute')
if not _python_cmd('setup.py', 'install'):
log.warn('Something went wrong during the installation.')
log.warn('See the error message above.')
finally:
os.chdir(old_wd)
def _build_egg(egg, tarball, to_dir):
# extracting the tarball
tmpdir = tempfile.mkdtemp()
log.warn('Extracting in %s', tmpdir)
old_wd = os.getcwd()
try:
os.chdir(tmpdir)
tar = tarfile.open(tarball)
_extractall(tar)
tar.close()
# going in the directory
subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
os.chdir(subdir)
log.warn('Now working in %s', subdir)
# building an egg
log.warn('Building a Distribute egg in %s', to_dir)
_python_cmd('setup.py', '-q', 'bdist_egg', '--dist-dir', to_dir)
finally:
os.chdir(old_wd)
# returning the result
log.warn(egg)
if not os.path.exists(egg):
raise IOError('Could not build the egg.')
def _do_download(version, download_base, to_dir, download_delay):
egg = os.path.join(to_dir, 'distribute-%s-py%d.%d.egg'
% (version, sys.version_info[0], sys.version_info[1]))
if not os.path.exists(egg):
tarball = download_setuptools(version, download_base,
to_dir, download_delay)
_build_egg(egg, tarball, to_dir)
sys.path.insert(0, egg)
import setuptools
setuptools.bootstrap_install_from = egg
def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
to_dir=os.curdir, download_delay=15, no_fake=True):
# making sure we use the absolute path
to_dir = os.path.abspath(to_dir)
was_imported = 'pkg_resources' in sys.modules or \
'setuptools' in sys.modules
try:
try:
import pkg_resources
if not hasattr(pkg_resources, '_distribute'):
if not no_fake:
_fake_setuptools()
raise ImportError
except ImportError:
return _do_download(version, download_base, to_dir, download_delay)
try:
pkg_resources.require("distribute>="+version)
return
except pkg_resources.VersionConflict:
e = sys.exc_info()[1]
if was_imported:
sys.stderr.write(
"The required version of distribute (>=%s) is not available,\n"
"and can't be installed while this script is running. Please\n"
"install a more recent version first, using\n"
"'easy_install -U distribute'."
"\n\n(Currently using %r)\n" % (version, e.args[0]))
sys.exit(2)
else:
del pkg_resources, sys.modules['pkg_resources'] # reload ok
return _do_download(version, download_base, to_dir,
download_delay)
except pkg_resources.DistributionNotFound:
return _do_download(version, download_base, to_dir,
download_delay)
finally:
if not no_fake:
_create_fake_setuptools_pkg_info(to_dir)
def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
to_dir=os.curdir, delay=15):
"""Download distribute from a specified location and return its filename
`version` should be a valid distribute version number that is available
as an egg for download under the `download_base` URL (which should end
with a '/'). `to_dir` is the directory where the egg will be downloaded.
`delay` is the number of seconds to pause before an actual download
attempt.
"""
# making sure we use the absolute path
to_dir = os.path.abspath(to_dir)
try:
from urllib.request import urlopen
except ImportError:
from urllib2 import urlopen
tgz_name = "distribute-%s.tar.gz" % version
url = download_base + tgz_name
saveto = os.path.join(to_dir, tgz_name)
src = dst = None
if not os.path.exists(saveto): # Avoid repeated downloads
try:
log.warn("Downloading %s", url)
src = urlopen(url)
# Read/write all in one block, so we don't create a corrupt file
# if the download is interrupted.
data = src.read()
dst = open(saveto, "wb")
dst.write(data)
finally:
if src:
src.close()
if dst:
dst.close()
return os.path.realpath(saveto)
def _no_sandbox(function):
def __no_sandbox(*args, **kw):
try:
from setuptools.sandbox import DirectorySandbox
if not hasattr(DirectorySandbox, '_old'):
def violation(*args):
pass
DirectorySandbox._old = DirectorySandbox._violation
DirectorySandbox._violation = violation
patched = True
else:
patched = False
except ImportError:
patched = False
try:
return function(*args, **kw)
finally:
if patched:
DirectorySandbox._violation = DirectorySandbox._old
del DirectorySandbox._old
return __no_sandbox
def _patch_file(path, content):
"""Will backup the file then patch it"""
existing_content = open(path).read()
if existing_content == content:
# already patched
log.warn('Already patched.')
return False
log.warn('Patching...')
_rename_path(path)
f = open(path, 'w')
try:
f.write(content)
finally:
f.close()
return True
_patch_file = _no_sandbox(_patch_file)
def _same_content(path, content):
return open(path).read() == content
def _rename_path(path):
new_name = path + '.OLD.%s' % time.time()
log.warn('Renaming %s into %s', path, new_name)
os.rename(path, new_name)
return new_name
def _remove_flat_installation(placeholder):
if not os.path.isdir(placeholder):
log.warn('Unkown installation at %s', placeholder)
return False
found = False
for file in os.listdir(placeholder):
if fnmatch.fnmatch(file, 'setuptools*.egg-info'):
found = True
break
if not found:
log.warn('Could not locate setuptools*.egg-info')
return
log.warn('Removing elements out of the way...')
pkg_info = os.path.join(placeholder, file)
if os.path.isdir(pkg_info):
patched = _patch_egg_dir(pkg_info)
else:
patched = _patch_file(pkg_info, SETUPTOOLS_PKG_INFO)
if not patched:
log.warn('%s already patched.', pkg_info)
return False
# now let's move the files out of the way
for element in ('setuptools', 'pkg_resources.py', 'site.py'):
element = os.path.join(placeholder, element)
if os.path.exists(element):
_rename_path(element)
else:
log.warn('Could not find the %s element of the '
'Setuptools distribution', element)
return True
_remove_flat_installation = _no_sandbox(_remove_flat_installation)
def _after_install(dist):
log.warn('After install bootstrap.')
placeholder = dist.get_command_obj('install').install_purelib
_create_fake_setuptools_pkg_info(placeholder)
def _create_fake_setuptools_pkg_info(placeholder):
if not placeholder or not os.path.exists(placeholder):
log.warn('Could not find the install location')
return
pyver = '%s.%s' % (sys.version_info[0], sys.version_info[1])
setuptools_file = 'setuptools-%s-py%s.egg-info' % \
(SETUPTOOLS_FAKED_VERSION, pyver)
pkg_info = os.path.join(placeholder, setuptools_file)
if os.path.exists(pkg_info):
log.warn('%s already exists', pkg_info)
return
log.warn('Creating %s', pkg_info)
f = open(pkg_info, 'w')
try:
f.write(SETUPTOOLS_PKG_INFO)
finally:
f.close()
pth_file = os.path.join(placeholder, 'setuptools.pth')
log.warn('Creating %s', pth_file)
f = open(pth_file, 'w')
try:
f.write(os.path.join(os.curdir, setuptools_file))
finally:
f.close()
_create_fake_setuptools_pkg_info = _no_sandbox(_create_fake_setuptools_pkg_info)
def _patch_egg_dir(path):
# let's check if it's already patched
pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO')
if os.path.exists(pkg_info):
if _same_content(pkg_info, SETUPTOOLS_PKG_INFO):
log.warn('%s already patched.', pkg_info)
return False
_rename_path(path)
os.mkdir(path)
os.mkdir(os.path.join(path, 'EGG-INFO'))
pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO')
f = open(pkg_info, 'w')
try:
f.write(SETUPTOOLS_PKG_INFO)
finally:
f.close()
return True
_patch_egg_dir = _no_sandbox(_patch_egg_dir)
def _before_install():
log.warn('Before install bootstrap.')
_fake_setuptools()
def _under_prefix(location):
if 'install' not in sys.argv:
return True
args = sys.argv[sys.argv.index('install')+1:]
for index, arg in enumerate(args):
for option in ('--root', '--prefix'):
if arg.startswith('%s=' % option):
top_dir = arg.split('root=')[-1]
return location.startswith(top_dir)
elif arg == option:
if len(args) > index:
top_dir = args[index+1]
return location.startswith(top_dir)
if arg == '--user' and USER_SITE is not None:
return location.startswith(USER_SITE)
return True
def _fake_setuptools():
log.warn('Scanning installed packages')
try:
import pkg_resources
except ImportError:
# we're cool
log.warn('Setuptools or Distribute does not seem to be installed.')
return
ws = pkg_resources.working_set
try:
setuptools_dist = ws.find(pkg_resources.Requirement.parse('setuptools',
replacement=False))
except TypeError:
# old distribute API
setuptools_dist = ws.find(pkg_resources.Requirement.parse('setuptools'))
if setuptools_dist is None:
log.warn('No setuptools distribution found')
return
# detecting if it was already faked
setuptools_location = setuptools_dist.location
log.warn('Setuptools installation detected at %s', setuptools_location)
# if --root or --preix was provided, and if
# setuptools is not located in them, we don't patch it
if not _under_prefix(setuptools_location):
log.warn('Not patching, --root or --prefix is installing Distribute'
' in another location')
return
# let's see if its an egg
if not setuptools_location.endswith('.egg'):
log.warn('Non-egg installation')
res = _remove_flat_installation(setuptools_location)
if not res:
return
else:
log.warn('Egg installation')
pkg_info = os.path.join(setuptools_location, 'EGG-INFO', 'PKG-INFO')
if (os.path.exists(pkg_info) and
_same_content(pkg_info, SETUPTOOLS_PKG_INFO)):
log.warn('Already patched.')
return
log.warn('Patching...')
# let's create a fake egg replacing setuptools one
res = _patch_egg_dir(setuptools_location)
if not res:
return
log.warn('Patched done.')
_relaunch()
def _relaunch():
log.warn('Relaunching...')
# we have to relaunch the process
# pip marker to avoid a relaunch bug
if sys.argv[:3] == ['-c', 'install', '--single-version-externally-managed']:
sys.argv[0] = 'setup.py'
args = [sys.executable] + sys.argv
sys.exit(subprocess.call(args))
def _extractall(self, path=".", members=None):
"""Extract all members from the archive to the current working
directory and set owner, modification time and permissions on
directories afterwards. `path' specifies a different directory
to extract to. `members' is optional and must be a subset of the
list returned by getmembers().
"""
import copy
import operator
from tarfile import ExtractError
directories = []
if members is None:
members = self
for tarinfo in members:
if tarinfo.isdir():
# Extract directories with a safe mode.
directories.append(tarinfo)
tarinfo = copy.copy(tarinfo)
tarinfo.mode = 448 # decimal for oct 0700
self.extract(tarinfo, path)
# Reverse sort directories.
if sys.version_info < (2, 4):
def sorter(dir1, dir2):
return cmp(dir1.name, dir2.name)
directories.sort(sorter)
directories.reverse()
else:
directories.sort(key=operator.attrgetter('name'), reverse=True)
# Set correct owner, mtime and filemode on directories.
for tarinfo in directories:
dirpath = os.path.join(path, tarinfo.name)
try:
self.chown(tarinfo, dirpath)
self.utime(tarinfo, dirpath)
self.chmod(tarinfo, dirpath)
except ExtractError:
e = sys.exc_info()[1]
if self.errorlevel > 1:
raise
else:
self._dbg(1, "tarfile: %s" % e)
def main(argv, version=DEFAULT_VERSION):
"""Install or upgrade setuptools and EasyInstall"""
tarball = download_setuptools()
_install(tarball)
if __name__ == '__main__':
main(sys.argv[1:])
...@@ -20,7 +20,7 @@ to be installed: ...@@ -20,7 +20,7 @@ to be installed:
We develop mainly on 64-bit Linux machines. 32-bit architectures are We develop mainly on 64-bit Linux machines. 32-bit architectures are
not well-tested. not well-tested.
Python >= 2.4 Python_ >= 2.4
Including the development package (``python-dev`` or ``python-devel`` Including the development package (``python-dev`` or ``python-devel``
on most Linux distributions). on most Linux distributions).
...@@ -34,7 +34,7 @@ to be installed: ...@@ -34,7 +34,7 @@ to be installed:
`SciPy <http://scipy.org>`_ `SciPy <http://scipy.org>`_
Only currently required for sparse matrix and special functions Only currently required for sparse matrix and special functions
support, but highly recommended. We recommend SciPy support, but *highly* recommended. We recommend SciPy
>=0.7 if you are using sparse matrices, because ``scipy.sparse`` >=0.7 if you are using sparse matrices, because ``scipy.sparse``
is buggy in 0.6 (the ``scipy.csc_matrix`` version of ``dot()`` has a is buggy in 0.6 (the ``scipy.csc_matrix`` version of ``dot()`` has a
bug with singleton dimensions, there may be more bugs). bug with singleton dimensions, there may be more bugs).
...@@ -46,6 +46,7 @@ to be installed: ...@@ -46,6 +46,7 @@ to be installed:
.. _BLAS: http://en.wikipedia.org/wiki/Basic_Linear_Algebra_Subprograms .. _BLAS: http://en.wikipedia.org/wiki/Basic_Linear_Algebra_Subprograms
.. _Accelerate framework: http://developer.apple.com/performance/accelerateframework.html .. _Accelerate framework: http://developer.apple.com/performance/accelerateframework.html
.. _Python: http://www.python.org/
The following libraries and software are optional: The following libraries and software are optional:
...@@ -54,83 +55,151 @@ The following libraries and software are optional: ...@@ -54,83 +55,151 @@ The following libraries and software are optional:
`Sphinx <http://sphinx.pocoo.org/>`_ >= 0.5.1, `pygments <http://pygments.org/>`_ `Sphinx <http://sphinx.pocoo.org/>`_ >= 0.5.1, `pygments <http://pygments.org/>`_
For building the documentation. LaTeX_ and dvipng_ are also necessary For building the documentation. LaTeX_ and dvipng_ are also necessary
for math to show up as images. for math to show up as images.
`Mercurial <http://www.selenic.com/mercurial/>`_ `Mercurial <http://mercurial.selenic.com/>`_
To download bleeding-edge versions of Theano. To download bleeding-edge versions of Theano.
`NVIDIA CUDA drivers and SDK `NVIDIA CUDA drivers and SDK`_
<http://developer.nvidia.com/object/gpucomputing.html>`_
Required for GPU code generation/execution. Only NVIDIA GPUs using Required for GPU code generation/execution. Only NVIDIA GPUs using
32-bit floating point numbers are currently supported. 32-bit floating point numbers are currently supported.
.. _LaTeX: http://www.latex-project.org/ .. _LaTeX: http://www.latex-project.org/
.. _dvipng: http://savannah.nongnu.org/projects/dvipng/ .. _dvipng: http://savannah.nongnu.org/projects/dvipng/
.. _NVIDIA CUDA drivers and SDK: http://developer.nvidia.com/object/gpucomputing.html
Basic user install instructions Basic user install instructions
------------------------------- -------------------------------
The easiest way to obtain the released version of Theano is from PyPI using The easiest way to obtain the released version of Theano is from PyPI using
the ``easy_install`` command provided by distribute_ (and it's predecessor, pip_ (a replacement for easy_install_ provided by setuptools_/distribute_)
`setuptools`_). If you have one of these installed, installing Theano should by typing
be simply a matter of::
.. code-block:: bash
pip install Theano
You may need to add ``sudo`` before this command to install into your
system's ``site-packages`` directory. If you do not have administrator access
to your machine, you can install to an alternate prefix using
.. code-block:: bash
pip install Theano --install-option='--prefix=YOURPREFIX'
easy_install Theano e.g. using ``--install-option='--prefix=~/.local'`` on Python 2.4 would
install Theano into ``.local/lib/python2.4/site-packages`` inside your home
directory on Mac OS X or Unix/Linux (this ``site-packages`` directory must be
listed in your ``$PYTHONPATH``; for Python 2.6 and later, ``~/.local`` is
automatically searched and does *not* need to be explicitly included in
``$PYTHONPATH``, see :ref:`config_pythonpath` for instructions).
Alternatively you can use virtualenv_ to create an isolated ``site-packages``
directory; see the `virtualenv documentation`_ for details.
.. note::
Theano *can* be installed with easy_install_, however we recommend pip_ as
a long-standing bug in ``easy_install`` prevents ``theano.test()`` from
running the Theano test suite; ``pip`` offers many other benefits over
``easy_install`` such as more intelligent dependency management, better
error messages and a ``pip uninstall`` command for easily removing
packages.
If you do not have ``pip`` installed but do have ``easy_install``, you can
get ``pip`` by simply typing ``easy_install pip``.
.. _distribute: http://packages.python.org/distribute/ .. _distribute: http://packages.python.org/distribute/
.. _setuptools: http://pypi.python.org/pypi/setuptools .. _setuptools: http://pypi.python.org/pypi/setuptools
.. _easy_install: http://packages.python.org/distribute/easy_install.html
.. _virtualenv: http://pypi.python.org/pypi/virtualenv
.. _virtualenv documentation: http://virtualenv.openplans.org/
.. _pip: http://pypi.python.org/pypi/pip
.. _install_bleeding_edge: .. _install_bleeding_edge:
Bleeding-edge (developer) install instructions Bleeding-edge (developer) install instructions
---------------------------------------------- ----------------------------------------------
If you are a developer of Theano, then check out the :ref:`dev_start_guide` If you are a developer of Theano, then check out the :ref:`dev_start_guide`.
guide.
The following are general instructions that will set you up with the The following are general instructions that will set you up with the
bleeding-edge version of Theano. First, get the code using `mercurial bleeding-edge version of Theano. First, get the code using `Mercurial
<http://www.selenic.com/mercurial/wiki/>`__: <http://mercurial.selenic.com/>`__:
.. code-block:: bash .. code-block:: bash
hg clone http://hg.assembla.com/theano Theano hg clone http://hg.assembla.com/theano Theano
Configuring ``PYTHONPATH`` From here, the easiest way to get started is
--------------------------
.. code-block:: bash
cd Theano
python setup.py develop
The subdirectory ``Theano/theano`` has to be located in a path mentioned in This will install a ``.pth`` file in your ``site-packages`` directory that
your ``PYTHONPATH``. In order to do that, you can either create a symbolic tells Python where to look for your Theano installation (i.e. in the
link to Theano/theano in a directory already mentioned in your ``PYTHONPATH`` directory your just checked out of Mercurial). Using ``develop`` mode is
environment variable, or modify the ``PYTHONPATH`` so that it mentions Theano. preferable to ``install`` as any modifications you make in the checkout
directory (or changes you pull with Mercurial) will be automatically reflected
in the "installed" version without re-running ``python setup.py install``.
To create a symbolic link: If you do not have permission to modify your ``site-packages`` directory you
can specify an alternative installation prefix using
.. code-block:: bash .. code-block:: bash
ln -s Theano/theano <someplace on your PYTHONPATH>/theano python setup.py develop --prefix=YOURPREFIX
A common choice is ``~/.local`` which is automatically searched for Python >=
2.6; for earlier Python versions and other installation prefixes, the prefix
specified must contain ``lib/pythonA.B/site-packages``, where ``A.B`` is e.g.
2.5, and this ``site-packages`` directory must be listed in ``$PYTHONPATH``.
An alternative, perhaps simpler way of creating and using an isolated
``site-packages`` is to use virtualenv_; see the `virtualenv documentation`_
for details. If you find yourself using virtualenv frequently you may find the
virtualenvwrapper_ package useful for switching between them.
.. _virtualenv: http://pypi.python.org/pypi/virtualenv
.. _virtualenv documentation: http://virtualenv.openplans.org/
.. _virtualenvwrapper: http://www.doughellmann.com/projects/virtualenvwrapper/
.. _config_pythonpath:
Configuring ``PYTHONPATH``
##########################
To modify the environment variable PYTHONPATH in bash, you may do this: To modify the environment variable ``PYTHONPATH`` in bash, you may do this:
.. code-block:: bash .. code-block:: bash
export PYTHONPATH=<path to Theano's parent dir>/Theano:$PYTHONPATH export PYTHONPATH=<new location to add>:$PYTHONPATH
In csh: In csh:
.. code-block:: csh .. code-block:: csh
setenv PYTHONPATH <path to Theano's parent dir>/Theano:$PYTHONPATH setenv PYTHONPATH <new location to add>:$PYTHONPATH
To make this change stick you'll usually need to add the command to one or
more of your shell's startup scripts, i.e. ``~/.bashrc`` or ``~/.cshrc``.
Consult your shell's documentation for details.
Testing your installation Testing your installation
--------------------------- ---------------------------
Once you have completed these steps, you should run the theano test suite like this: Once you have completed these steps, you should run the Theano test suite. At
a Python (or IPython) interpreter,
.. code-block:: bash .. code-block:: python
cd Theano >>> import theano
THEANO_FLAGS=warn.ignore_bug_before=all nosetests #execute all the tests >>> theano.test()
You can also run them in-place from the Mercurial checkout directory by typing
.. code-block:: bash
nosetests
``THEANO_FLAGS`` is an environment variable that define Theano flags ``THEANO_FLAGS`` is an environment variable that define Theano flags
(:ref:`libdoc_config`). For Windows users, you can remove it or see the (:ref:`libdoc_config`). For Windows users, you can remove it or see the
...@@ -144,7 +213,7 @@ the ``theano-users@googlegroups.com`` mailing list. ...@@ -144,7 +213,7 @@ the ``theano-users@googlegroups.com`` mailing list.
`warn.ignore_bug_before=all` removes warnings that you don't need to see `warn.ignore_bug_before=all` removes warnings that you don't need to see
here. It is also recommended for a new user to set this flag to a here. It is also recommended for a new user to set this flag to a
different value into their .theanorc file. See different value in their ``.theanorc`` file. See
:attr:`config.warn.ignore_bug_before` for more details. :attr:`config.warn.ignore_bug_before` for more details.
Troubleshooting: Make sure you have a BLAS library Troubleshooting: Make sure you have a BLAS library
...@@ -169,7 +238,6 @@ entry like this: ...@@ -169,7 +238,6 @@ entry like this:
.. code-block:: cfg .. code-block:: cfg
# other stuff can go here # other stuff can go here
[blas] [blas]
ldflags = -lf77blas -latlas -lgfortran #put your flags here ldflags = -lf77blas -latlas -lgfortran #put your flags here
......
...@@ -100,8 +100,9 @@ Nightly test ...@@ -100,8 +100,9 @@ Nightly test
============ ============
Each night we execute all the unit tests automatically. The result is sent by Each night we execute all the unit tests automatically. The result is sent by
email to one of the developers, who (at his discretion) forwards it to the email to the `theano-buildbot`_ mailing list.
mailing list. Said developer may not read his email obsessively (especially
on the weekend) so there might be some latency in the process. For more .. _theano-buildbot: https://groups.google.com/group/theano-buildbot
detail :ref:`see <metadocumentation_nightly_build>`.
For more detail, see :ref:`see <metadocumentation_nightly_build>`.
...@@ -129,33 +129,19 @@ You can see a list of all `pylint messages ...@@ -129,33 +129,19 @@ You can see a list of all `pylint messages
The nightly build/tests process The nightly build/tests process
--------------------------------------- ---------------------------------------
The user ``lisa`` runs a cronjob on the computer ``boltzmann``. The user ``lisa`` runs a cronjob on the computer ``ceylon``, this
This happens nightly. happens nightly. (To have the crontab executed, the ``lisa`` user must
The cronjob executes the script ``~/www/nightly_build/do_nightly_build_theano``. be logged into ``ceylon``, Fred leaves a shell open for that.)
This script performs a an "hg pull -u" of theano (and pylearn too).
Then it executes something like
.. code-block:: bash The cronjob executes the scripts
``~/nightly_build/do_nightly_build_{theano,pylearn,deeplearning}``.
THEANO_FLAGS='unittests.rseed=<SEED>,mode=DEBUG_MODE' /usr/bin/nosetests --with-coverage --cover-package=theano --cover-package=pylearn These scripts perform an "hg pull -u" of theano (and pylearn, and
DeepLearningTutorials too), and execute nosetests (in various settings).
in the updated ``theano`` directory.
The output is emailed automatically to one of the developers.
This line is executed with a several fixed ``SEED`` values in DEBUG_MODE. It
is executed in FAST_RUN and FAST_COMPILE with just one SEED value.
We can't email directly to the mailing list as it is emailed as the root user. The output is emailed automatically to the `theano-buildbot`_ mailing list.
We haven't yet found a way to have google groups accept email from a user without sending an email to it.
As we don't have root control from this domain, we won't receive the email.
We haven't pursued the option of configuring the ``lisa`` account to send
email from an official gmail account.
Also, to have the crontab executed, *the ``lisa`` user must be logged into .. _theano-buildbot: https://groups.google.com/group/theano-buildbot
``boltzmann``*.
In a nutshell: Fred keeps a shell open on boltzmann at all times, gets the
email, and forwards it to the mailing list when something interesting shows up
in the report.
TO WRITE TO WRITE
--------------------------------------- ---------------------------------------
......
...@@ -4,11 +4,21 @@ ...@@ -4,11 +4,21 @@
# * Figure out how to compile and install documentation automatically # * Figure out how to compile and install documentation automatically
# * Add download_url # * Add download_url
# Detect whether or not the user has setuptools and use the bundled
# distribute_setup.py bootstrap module if they don't.
try:
from setuptools import setup, find_packages
except ImportError:
import distribute_setup
distribute_setup.use_setuptools()
from setuptools import setup, find_packages
import os import os
import subprocess import subprocess
CLASSIFIERS = """\ CLASSIFIERS = """\
Development Status :: 4 - Beta Development Status :: 4 - Beta
Intended Audience :: Education
Intended Audience :: Science/Research Intended Audience :: Science/Research
Intended Audience :: Developers Intended Audience :: Developers
License :: OSI Approved :: BSD License License :: OSI Approved :: BSD License
...@@ -26,7 +36,7 @@ MAINTAINER = "LISA laboratory, University of Montreal" ...@@ -26,7 +36,7 @@ MAINTAINER = "LISA laboratory, University of Montreal"
MAINTAINER_EMAIL = "theano-dev@googlegroups.com" MAINTAINER_EMAIL = "theano-dev@googlegroups.com"
DESCRIPTION = ('Optimizing compiler for evaluating mathematical ' + DESCRIPTION = ('Optimizing compiler for evaluating mathematical ' +
'expressions on CPUs and GPUs.') 'expressions on CPUs and GPUs.')
LONG_DESCRIPTION = "" LONG_DESCRIPTION = open("DESCRIPTION.txt").read()
URL = "http://deeplearning.net/software/theano/" URL = "http://deeplearning.net/software/theano/"
DOWNLOAD_URL = "" DOWNLOAD_URL = ""
LICENSE = 'BSD' LICENSE = 'BSD'
...@@ -37,7 +47,7 @@ PLATFORMS = ["Windows", "Linux", "Solaris", "Mac OS-X", "Unix"] ...@@ -37,7 +47,7 @@ PLATFORMS = ["Windows", "Linux", "Solaris", "Mac OS-X", "Unix"]
MAJOR = 0 MAJOR = 0
MINOR = 3 MINOR = 3
MICRO = 0 MICRO = 0
SUFFIX = "rc3" # Should be blank except for rc's, betas, etc. SUFFIX = "rc4" # Should be blank except for rc's, betas, etc.
ISRELEASED = False ISRELEASED = False
VERSION = '%d.%d.%d%s' % (MAJOR, MINOR, MICRO, SUFFIX) VERSION = '%d.%d.%d%s' % (MAJOR, MINOR, MICRO, SUFFIX)
...@@ -106,14 +116,16 @@ if not release: ...@@ -106,14 +116,16 @@ if not release:
def do_setup(): def do_setup():
write_version_py() write_version_py()
from setuptools import setup, find_packages
setup(name=NAME, setup(name=NAME,
version=VERSION, version=VERSION,
description=DESCRIPTION, description=DESCRIPTION,
long_description=LONG_DESCRIPTION,
classifiers=CLASSIFIERS,
author=AUTHOR, author=AUTHOR,
author_email=AUTHOR_EMAIL, author_email=AUTHOR_EMAIL,
url=URL, url=URL,
license=LICENSE, license=LICENSE,
platforms=PLATFORMS,
packages=find_packages(), packages=find_packages(),
install_requires=['numpy>=1.3.0', 'scipy>=0.7.0'], install_requires=['numpy>=1.3.0', 'scipy>=0.7.0'],
package_data={ package_data={
......
...@@ -110,7 +110,4 @@ try: ...@@ -110,7 +110,4 @@ try:
import theano.version import theano.version
__version__ = theano.version.version __version__ = theano.version.version
except ImportError: except ImportError:
import warnings __version__ = "unknown"
warnings.warn(
"version.py could not be imported. Run setup.py at least once to generate it"
)
import atexit, gc, os, stat import atexit, os, stat
from theano.compile import optdb from theano.compile import optdb
from theano import config from theano import config
...@@ -96,9 +96,6 @@ if cuda_available: ...@@ -96,9 +96,6 @@ if cuda_available:
cuda_initialization_error_message = "" cuda_initialization_error_message = ""
# actively closing our gpu session presents segfault-on-exit on some systems # actively closing our gpu session presents segfault-on-exit on some systems
atexit.register(gpu_shutdown) atexit.register(gpu_shutdown)
# do garbage collection before releasing the gpu to avoid releasing invalid pointers later
# note that atexit-registered calls are called in LIFO order
atexit.register(gc.collect)
except EnvironmentError, e: except EnvironmentError, e:
cuda_available = False cuda_available = False
cuda_initialization_error_message = e.message cuda_initialization_error_message = e.message
......
...@@ -12,11 +12,43 @@ ...@@ -12,11 +12,43 @@
//If true, we fill with NAN allocated device memory. //If true, we fill with NAN allocated device memory.
#define ALLOC_MEMSET 0 #define ALLOC_MEMSET 0
#define DEBUG_GPU_CONTEXT_REFCOUNT 0
// g_gpu_context_refcount starts at one b/c the gpu context will be implicitly created
// on the first successful cuda call. the matching decref is in CudaNdarray_gpu_shutdown.
static int g_gpu_context_refcount = 1;
///////////////////////////
// cuda context management
///////////////////////////
void gpu_context_incref() {
g_gpu_context_refcount++;
#if DEBUG_GPU_CONTEXT_REFCOUNT
fprintf(stderr, "gpu_context_incref, to %d\n", g_gpu_context_refcount);
#endif
}
void gpu_context_decref() {
g_gpu_context_refcount--;
#if DEBUG_GPU_CONTEXT_REFCOUNT
fprintf(stderr, "gpu_context_decref, to %d\n", g_gpu_context_refcount);
#endif
if(g_gpu_context_refcount == 0) {
// we're now free to close the cuda context; if we don't explicitly
// exit our cuda context, some systems segfault on process exit
// for as-yet unknown reasons; see
// http://groups.google.com/group/theano-users/browse_thread/thread/c351846e5cebe35f
cudaThreadExit();
#if DEBUG_GPU_CONTEXT_REFCOUNT
fprintf(stderr, "gpu_context_decref at 0, calling cudaThreadExit\n");
#endif
}
}
///////////////////////// /////////////////////////
// Alloc and Free // Alloc and Free
///////////////////////// /////////////////////////
/** /**
* *
* In the test program I'm using, the _outstanding_mallocs decreases with every call. * In the test program I'm using, the _outstanding_mallocs decreases with every call.
...@@ -48,6 +80,9 @@ void * device_malloc(size_t size) ...@@ -48,6 +80,9 @@ void * device_malloc(size_t size)
return NULL; return NULL;
} }
_outstanding_mallocs[0] += (rval != NULL); _outstanding_mallocs[0] += (rval != NULL);
if(rval != NULL) {
gpu_context_incref(); // keep the gpu context around until we've free this memory
}
#if COMPUTE_GPU_MEM_USED #if COMPUTE_GPU_MEM_USED
for(int i=0;i<TABLE_SIZE;i++){ for(int i=0;i<TABLE_SIZE;i++){
if(NULL==_alloc_size_table[i].ptr){ if(NULL==_alloc_size_table[i].ptr){
...@@ -81,6 +116,9 @@ int device_free(void *ptr) ...@@ -81,6 +116,9 @@ int device_free(void *ptr)
return -1; return -1;
} }
_outstanding_mallocs[0] -= (ptr != NULL); _outstanding_mallocs[0] -= (ptr != NULL);
if(ptr != NULL) {
gpu_context_decref();
}
#if COMPUTE_GPU_MEM_USED #if COMPUTE_GPU_MEM_USED
int i=0; int i=0;
for(;i<TABLE_SIZE;i++) for(;i<TABLE_SIZE;i++)
...@@ -1888,7 +1926,7 @@ CudaNdarray_gpu_init(PyObject* _unused, PyObject* args) ...@@ -1888,7 +1926,7 @@ CudaNdarray_gpu_init(PyObject* _unused, PyObject* args)
PyObject * PyObject *
CudaNdarray_gpu_shutdown(PyObject* _unused, PyObject* _unused_args) { CudaNdarray_gpu_shutdown(PyObject* _unused, PyObject* _unused_args) {
cudaThreadExit(); gpu_context_decref();
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
} }
......
...@@ -812,8 +812,8 @@ def test_shared_float32(): ...@@ -812,8 +812,8 @@ def test_shared_float32():
del theano.shared.constructors[-1] del theano.shared.constructors[-1]
import theano.tensor.tests.test_basic import theano.tensor.tests.test_sharedvar
test_shared_options = theano.tensor.tests.test_basic.makeSharedTester( test_shared_options = theano.tensor.tests.test_sharedvar.makeSharedTester(
tcn.shared_constructor, 'float32', False, False, False, tcn.shared_constructor, 'float32', False, False, False,
cuda_ndarray.CudaNdarray, cuda_ndarray.CudaNdarray,
lambda a: isinstance(a,cuda_ndarray.CudaNdarray), lambda a: isinstance(a,cuda_ndarray.CudaNdarray),
......
...@@ -23,6 +23,7 @@ from theano.sparse import csc_from_dense, csr_from_dense, dense_from_sparse ...@@ -23,6 +23,7 @@ from theano.sparse import csc_from_dense, csr_from_dense, dense_from_sparse
from theano.tests import unittest_tools as utt from theano.tests import unittest_tools as utt
from theano import tensor from theano import tensor
from theano.tensor.basic import _allclose
def eval_outputs(outputs): def eval_outputs(outputs):
...@@ -298,7 +299,7 @@ class test_structureddot(unittest.TestCase): ...@@ -298,7 +299,7 @@ class test_structureddot(unittest.TestCase):
scipy_result = spmat * mat scipy_result = spmat * mat
assert theano_result.shape == scipy_result.shape assert theano_result.shape == scipy_result.shape
assert theano_result.dtype == scipy_result.dtype assert theano_result.dtype == scipy_result.dtype
assert numpy.allclose(theano_result, scipy_result) assert _allclose(theano_result, scipy_result)
def test_opt_unpack(self): def test_opt_unpack(self):
...@@ -440,8 +441,8 @@ class test_structureddot(unittest.TestCase): ...@@ -440,8 +441,8 @@ class test_structureddot(unittest.TestCase):
self.failUnless(numpy.allclose(theano_result, scipy_result)) self.failUnless(numpy.allclose(theano_result, scipy_result))
self.failIf(theano_time > overhead_rtol*scipy_time + overhead_tol) self.failIf(theano_time > overhead_rtol*scipy_time + overhead_tol)
import theano.tensor.tests.test_basic import theano.tensor.tests.test_sharedvar
test_shared_options=theano.tensor.tests.test_basic.makeSharedTester( test_shared_options=theano.tensor.tests.test_sharedvar.makeSharedTester(
theano.sparse.shared, 'float64', theano.sparse.shared, 'float64',
True, True, True, scipy.sparse.csc_matrix, scipy.sparse.issparse, True, True, True, scipy.sparse.csc_matrix, scipy.sparse.issparse,
lambda a: dense_from_sparse(a*2.), lambda a: dense_from_sparse(a*2.),
......
...@@ -321,6 +321,11 @@ def _allclose(a, b): ...@@ -321,6 +321,11 @@ def _allclose(a, b):
else: else:
atol = float64_atol atol = float64_atol
rtol = float64_rtol rtol = float64_rtol
# Work around bug in Numpy, see http://projects.scipy.org/numpy/ticket/1684
if str(b.dtype).startswith('int') and (numpy.absolute(b) < 0).any():
b = theano._asarray(b, dtype='float64')
return numpy.allclose(a,b, atol=atol, rtol=rtol) return numpy.allclose(a,b, atol=atol, rtol=rtol)
def get_constant_value(v): def get_constant_value(v):
......
...@@ -3440,202 +3440,6 @@ def test_dimshuffle_duplicate(): ...@@ -3440,202 +3440,6 @@ def test_dimshuffle_duplicate():
assert success assert success
def makeSharedTester(shared_constructor_,
dtype_,
get_value_borrow_true_alias_,
shared_borrow_true_alias_,
set_value_borrow_true_alias_,
internal_type_,
test_internal_type_,
theano_fct_,
ref_fct_,
cast_value_ = numpy.asarray,
add_matrix_ = False):
"""
This is a generic fct to allow reusing the same test function
for many shared variable of many types.
We must use /= as sparse type don't support other inplace operation.
"""
class SharedTester(unittest.TestCase):
shared_constructor = staticmethod(shared_constructor_)
dtype = dtype_
get_value_borrow_true_alias = get_value_borrow_true_alias_
shared_borrow_true_alias = shared_borrow_true_alias_
internal_type = internal_type_
test_internal_type = staticmethod(test_internal_type_)
theano_fct = staticmethod(theano_fct_)
ref_fct = staticmethod(ref_fct_)
set_value_borrow_true_alias = set_value_borrow_true_alias_
cast_value = staticmethod(cast_value_)
add_matrix = add_matrix_
def test_shared_dont_alias(self):
dtype = self.dtype
if dtype is None:
dtype = theano.config.floatX
rng = numpy.random.RandomState([3,5,17])
x = numpy.asarray(rng.uniform(0,1,[2,4]),dtype=dtype)
x = self.cast_value(x)
x_ref = self.ref_fct(x)
x_shared = self.shared_constructor(x, borrow = False)
total = self.theano_fct(x_shared)
total_func = theano.function([],total)
total_val = total_func()
assert numpy.allclose(self.ref_fct(x), total_val)
x /= .5
total_val_2 = total_func()
#value used to construct should not alias with internal
assert numpy.allclose(total_val, total_val_2)
x = x_shared.get_value(borrow = False)
x /= .5
total_val_3 = total_func()
#value returned by access should not alias with internal
assert numpy.allclose(total_val, total_val_3)
#in this case we can alias
x = x_shared.get_value(borrow = True)
x /= .5
#this is not required by the contract but it is a feature we've
#implemented for some type of SharedVariable.
if self.get_value_borrow_true_alias:
assert numpy.allclose(self.ref_fct(x), total_func())
else:
assert numpy.allclose(x_ref, total_func())
def test_return_internal_type(self):
dtype = self.dtype
if dtype is None:
dtype = theano.config.floatX
rng = numpy.random.RandomState([3,5,17])
x = numpy.asarray(rng.uniform(0,1,[2,4]),dtype=dtype)
x = self.cast_value(x)
x_ref = self.ref_fct(x)
x_shared = self.shared_constructor(x, borrow = False)
total = self.theano_fct(x_shared)
total_func = theano.function([],total)
#in this case we can alias with the internal value
x = x_shared.get_value(borrow = True, return_internal_type = True)
assert self.test_internal_type(x)
values_to_add = .5
if self.add_matrix:
values_to_add = self.internal_type(numpy.ones(x.shape,dtype=dtype)/2)#supported for cudandarray, but not ndarray.
x /= values_to_add#supported by ndarray and CudaNdarray
#this is not required by the contract but it is a feature we can
#implement for some type of SharedVariable.
assert numpy.allclose(self.ref_fct(x), total_func())
x = x_shared.get_value(borrow = False, return_internal_type = True)
assert self.test_internal_type(x)
assert x is not x_shared.container.value
x /= values_to_add#supported by ndarray and CudaNdarray
#this is required by the contract
assert not numpy.allclose(self.ref_fct(x), total_func())
def test_set_value(self):
dtype = self.dtype
if dtype is None:
dtype = theano.config.floatX
rng = numpy.random.RandomState([3,5,17])
x = numpy.asarray(rng.uniform(0,1,[2,4]),dtype=dtype)
x = self.cast_value(x)
x_orig = x
x_orig_copy = x.copy()
x_ref = self.ref_fct(x)
x_shared = self.shared_constructor(x, borrow = False)
total = self.theano_fct(x_shared)
total_func = theano.function([],total)
#test if that theano shared variable optimize set_value(borrow=True)
get_x = x_shared.get_value(borrow=True)
assert get_x is not x_orig#borrow=False to shared_constructor
get_x /= .5
x_shared.set_value(get_x, borrow=True)
x = x_shared.get_value(borrow=True)
if self.set_value_borrow_true_alias:
assert x is get_x
else:
assert x is not get_x
assert numpy.allclose(self.ref_fct(x_orig/.5),self.ref_fct(x))
#test optimized get set value on the gpu(don't pass data to the cpu)
get_x = x_shared.get_value(borrow=True, return_internal_type=True)
assert get_x is not x_orig#borrow=False to shared_constructor
assert self.test_internal_type(get_x)
values_to_add = .5
if self.add_matrix:
values_to_add = self.internal_type(numpy.ones(x.shape,dtype=dtype)/2)#supported for cudandarray, but not ndarray.
assert self.test_internal_type(values_to_add)
get_x /= values_to_add#supported by ndarray and CudaNdarray
assert self.test_internal_type(get_x)
x_shared.set_value(get_x, borrow=True)
x = x_shared.get_value(borrow=True, return_internal_type=True)
assert self.test_internal_type(x)
assert x is get_x
################ TODO test Out.
def test_shared_do_alias(self):
dtype = self.dtype
if dtype is None:
dtype = theano.config.floatX
rng = numpy.random.RandomState([2,4,16])
x = numpy.asarray(rng.uniform(1,2,[4,2]),dtype=dtype)
x = self.cast_value(x)
x_ref = self.ref_fct(x)
x_shared = self.shared_constructor(x, borrow = True)
total = self.theano_fct(x_shared)
total_func = theano.function([],total)
total_val = total_func()
assert numpy.allclose(self.ref_fct(x), total_val)
x /= .5
#not required by the contract but it is a feature we've implemented
if self.shared_borrow_true_alias:
assert numpy.allclose(self.ref_fct(x), total_func())
else:
assert numpy.allclose(x_ref, total_func())
return SharedTester
test_shared_options=makeSharedTester(tensor.shared, 'float64',
True, True, True,
numpy.ndarray,
lambda a: isinstance(a,numpy.ndarray),
theano.tensor.sum,
numpy.sum)
if __name__ == '__main__': if __name__ == '__main__':
if 1: if 1:
unittest.main() unittest.main()
......
import numpy
import unittest
import theano
from theano import tensor
def makeSharedTester(shared_constructor_,
dtype_,
get_value_borrow_true_alias_,
shared_borrow_true_alias_,
set_value_borrow_true_alias_,
internal_type_,
test_internal_type_,
theano_fct_,
ref_fct_,
cast_value_ = numpy.asarray,
add_matrix_ = False):
"""
This is a generic fct to allow reusing the same test function
for many shared variable of many types.
We must use /= as sparse type don't support other inplace operation.
"""
class SharedTester(unittest.TestCase):
shared_constructor = staticmethod(shared_constructor_)
dtype = dtype_
get_value_borrow_true_alias = get_value_borrow_true_alias_
shared_borrow_true_alias = shared_borrow_true_alias_
internal_type = internal_type_
test_internal_type = staticmethod(test_internal_type_)
theano_fct = staticmethod(theano_fct_)
ref_fct = staticmethod(ref_fct_)
set_value_borrow_true_alias = set_value_borrow_true_alias_
cast_value = staticmethod(cast_value_)
add_matrix = add_matrix_
def test_shared_dont_alias(self):
dtype = self.dtype
if dtype is None:
dtype = theano.config.floatX
rng = numpy.random.RandomState([3,5,17])
x = numpy.asarray(rng.uniform(0,1,[2,4]),dtype=dtype)
x = self.cast_value(x)
x_ref = self.ref_fct(x)
x_shared = self.shared_constructor(x, borrow = False)
total = self.theano_fct(x_shared)
total_func = theano.function([],total)
total_val = total_func()
assert numpy.allclose(self.ref_fct(x), total_val)
x /= .5
total_val_2 = total_func()
#value used to construct should not alias with internal
assert numpy.allclose(total_val, total_val_2)
x = x_shared.get_value(borrow = False)
x /= .5
total_val_3 = total_func()
#value returned by access should not alias with internal
assert numpy.allclose(total_val, total_val_3)
#in this case we can alias
x = x_shared.get_value(borrow = True)
x /= .5
#this is not required by the contract but it is a feature we've
#implemented for some type of SharedVariable.
if self.get_value_borrow_true_alias:
assert numpy.allclose(self.ref_fct(x), total_func())
else:
assert numpy.allclose(x_ref, total_func())
def test_return_internal_type(self):
dtype = self.dtype
if dtype is None:
dtype = theano.config.floatX
rng = numpy.random.RandomState([3,5,17])
x = numpy.asarray(rng.uniform(0,1,[2,4]),dtype=dtype)
x = self.cast_value(x)
x_ref = self.ref_fct(x)
x_shared = self.shared_constructor(x, borrow = False)
total = self.theano_fct(x_shared)
total_func = theano.function([],total)
#in this case we can alias with the internal value
x = x_shared.get_value(borrow = True, return_internal_type = True)
assert self.test_internal_type(x)
values_to_add = .5
if self.add_matrix:
values_to_add = self.internal_type(numpy.ones(x.shape,dtype=dtype)/2)#supported for cudandarray, but not ndarray.
x /= values_to_add#supported by ndarray and CudaNdarray
#this is not required by the contract but it is a feature we can
#implement for some type of SharedVariable.
assert numpy.allclose(self.ref_fct(x), total_func())
x = x_shared.get_value(borrow = False, return_internal_type = True)
assert self.test_internal_type(x)
assert x is not x_shared.container.value
x /= values_to_add#supported by ndarray and CudaNdarray
#this is required by the contract
assert not numpy.allclose(self.ref_fct(x), total_func())
def test_set_value(self):
dtype = self.dtype
if dtype is None:
dtype = theano.config.floatX
rng = numpy.random.RandomState([3,5,17])
x = numpy.asarray(rng.uniform(0,1,[2,4]),dtype=dtype)
x = self.cast_value(x)
x_orig = x
x_orig_copy = x.copy()
x_ref = self.ref_fct(x)
x_shared = self.shared_constructor(x, borrow = False)
total = self.theano_fct(x_shared)
total_func = theano.function([],total)
#test if that theano shared variable optimize set_value(borrow=True)
get_x = x_shared.get_value(borrow=True)
assert get_x is not x_orig#borrow=False to shared_constructor
get_x /= .5
x_shared.set_value(get_x, borrow=True)
x = x_shared.get_value(borrow=True)
if self.set_value_borrow_true_alias:
assert x is get_x
else:
assert x is not get_x
assert numpy.allclose(self.ref_fct(x_orig/.5),self.ref_fct(x))
#test optimized get set value on the gpu(don't pass data to the cpu)
get_x = x_shared.get_value(borrow=True, return_internal_type=True)
assert get_x is not x_orig#borrow=False to shared_constructor
assert self.test_internal_type(get_x)
values_to_add = .5
if self.add_matrix:
values_to_add = self.internal_type(numpy.ones(x.shape,dtype=dtype)/2)#supported for cudandarray, but not ndarray.
assert self.test_internal_type(values_to_add)
get_x /= values_to_add#supported by ndarray and CudaNdarray
assert self.test_internal_type(get_x)
x_shared.set_value(get_x, borrow=True)
x = x_shared.get_value(borrow=True, return_internal_type=True)
assert self.test_internal_type(x)
assert x is get_x
################ TODO test Out.
def test_shared_do_alias(self):
dtype = self.dtype
if dtype is None:
dtype = theano.config.floatX
rng = numpy.random.RandomState([2,4,16])
x = numpy.asarray(rng.uniform(1,2,[4,2]),dtype=dtype)
x = self.cast_value(x)
x_ref = self.ref_fct(x)
x_shared = self.shared_constructor(x, borrow = True)
total = self.theano_fct(x_shared)
total_func = theano.function([],total)
total_val = total_func()
assert numpy.allclose(self.ref_fct(x), total_val)
x /= .5
#not required by the contract but it is a feature we've implemented
if self.shared_borrow_true_alias:
assert numpy.allclose(self.ref_fct(x), total_func())
else:
assert numpy.allclose(x_ref, total_func())
return SharedTester
test_shared_options=makeSharedTester(tensor.shared, 'float64',
True, True, True,
numpy.ndarray,
lambda a: isinstance(a,numpy.ndarray),
theano.tensor.sum,
numpy.sum)
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论