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

Merged

......@@ -24,3 +24,5 @@ pull.sh
setuptools-*.egg
theano/version.py
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
global-include *.cuh
global-include *.sh
include ChangeLog
include distribute_setup.py
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:
......
#!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:
We develop mainly on 64-bit Linux machines. 32-bit architectures are
not well-tested.
Python >= 2.4
Python_ >= 2.4
Including the development package (``python-dev`` or ``python-devel``
on most Linux distributions).
......@@ -34,7 +34,7 @@ to be installed:
`SciPy <http://scipy.org>`_
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``
is buggy in 0.6 (the ``scipy.csc_matrix`` version of ``dot()`` has a
bug with singleton dimensions, there may be more bugs).
......@@ -46,6 +46,7 @@ to be installed:
.. _BLAS: http://en.wikipedia.org/wiki/Basic_Linear_Algebra_Subprograms
.. _Accelerate framework: http://developer.apple.com/performance/accelerateframework.html
.. _Python: http://www.python.org/
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/>`_
For building the documentation. LaTeX_ and dvipng_ are also necessary
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.
`NVIDIA CUDA drivers and SDK
<http://developer.nvidia.com/object/gpucomputing.html>`_
`NVIDIA CUDA drivers and SDK`_
Required for GPU code generation/execution. Only NVIDIA GPUs using
32-bit floating point numbers are currently supported.
.. _LaTeX: http://www.latex-project.org/
.. _dvipng: http://savannah.nongnu.org/projects/dvipng/
.. _NVIDIA CUDA drivers and SDK: http://developer.nvidia.com/object/gpucomputing.html
Basic user install instructions
-------------------------------
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,
`setuptools`_). If you have one of these installed, installing Theano should
be simply a matter of::
pip_ (a replacement for easy_install_ provided by setuptools_/distribute_)
by typing
.. 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/
.. _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:
Bleeding-edge (developer) install instructions
----------------------------------------------
If you are a developer of Theano, then check out the :ref:`dev_start_guide`
guide.
If you are a developer of Theano, then check out the :ref:`dev_start_guide`.
The following are general instructions that will set you up with the
bleeding-edge version of Theano. First, get the code using `mercurial
<http://www.selenic.com/mercurial/wiki/>`__:
bleeding-edge version of Theano. First, get the code using `Mercurial
<http://mercurial.selenic.com/>`__:
.. code-block:: bash
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
your ``PYTHONPATH``. In order to do that, you can either create a symbolic
link to Theano/theano in a directory already mentioned in your ``PYTHONPATH``
environment variable, or modify the ``PYTHONPATH`` so that it mentions Theano.
This will install a ``.pth`` file in your ``site-packages`` directory that
tells Python where to look for your Theano installation (i.e. in the
directory your just checked out of Mercurial). Using ``develop`` mode is
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
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
export PYTHONPATH=<path to Theano's parent dir>/Theano:$PYTHONPATH
export PYTHONPATH=<new location to add>:$PYTHONPATH
In 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
---------------------------
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
THEANO_FLAGS=warn.ignore_bug_before=all nosetests #execute all the tests
>>> import theano
>>> 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
(:ref:`libdoc_config`). For Windows users, you can remove it or see the
......@@ -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
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.
Troubleshooting: Make sure you have a BLAS library
......@@ -169,7 +238,6 @@ entry like this:
.. code-block:: cfg
# other stuff can go here
[blas]
ldflags = -lf77blas -latlas -lgfortran #put your flags here
......
......@@ -100,8 +100,9 @@ Nightly test
============
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
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
detail :ref:`see <metadocumentation_nightly_build>`.
email to the `theano-buildbot`_ mailing list.
.. _theano-buildbot: https://groups.google.com/group/theano-buildbot
For more detail, see :ref:`see <metadocumentation_nightly_build>`.
......@@ -129,33 +129,19 @@ You can see a list of all `pylint messages
The nightly build/tests process
---------------------------------------
The user ``lisa`` runs a cronjob on the computer ``boltzmann``.
This happens nightly.
The cronjob executes the script ``~/www/nightly_build/do_nightly_build_theano``.
This script performs a an "hg pull -u" of theano (and pylearn too).
Then it executes something like
The user ``lisa`` runs a cronjob on the computer ``ceylon``, this
happens nightly. (To have the crontab executed, the ``lisa`` user must
be logged into ``ceylon``, Fred leaves a shell open for that.)
.. code-block:: bash
THEANO_FLAGS='unittests.rseed=<SEED>,mode=DEBUG_MODE' /usr/bin/nosetests --with-coverage --cover-package=theano --cover-package=pylearn
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.
The cronjob executes the scripts
``~/nightly_build/do_nightly_build_{theano,pylearn,deeplearning}``.
These scripts perform an "hg pull -u" of theano (and pylearn, and
DeepLearningTutorials too), and execute nosetests (in various settings).
We can't email directly to the mailing list as it is emailed as the root user.
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.
The output is emailed automatically to the `theano-buildbot`_ mailing list.
Also, to have the crontab executed, *the ``lisa`` user must be logged into
``boltzmann``*.
.. _theano-buildbot: https://groups.google.com/group/theano-buildbot
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
---------------------------------------
......
......@@ -4,11 +4,21 @@
# * Figure out how to compile and install documentation automatically
# * 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 subprocess
CLASSIFIERS = """\
Development Status :: 4 - Beta
Intended Audience :: Education
Intended Audience :: Science/Research
Intended Audience :: Developers
License :: OSI Approved :: BSD License
......@@ -26,7 +36,7 @@ MAINTAINER = "LISA laboratory, University of Montreal"
MAINTAINER_EMAIL = "theano-dev@googlegroups.com"
DESCRIPTION = ('Optimizing compiler for evaluating mathematical ' +
'expressions on CPUs and GPUs.')
LONG_DESCRIPTION = ""
LONG_DESCRIPTION = open("DESCRIPTION.txt").read()
URL = "http://deeplearning.net/software/theano/"
DOWNLOAD_URL = ""
LICENSE = 'BSD'
......@@ -37,7 +47,7 @@ PLATFORMS = ["Windows", "Linux", "Solaris", "Mac OS-X", "Unix"]
MAJOR = 0
MINOR = 3
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
VERSION = '%d.%d.%d%s' % (MAJOR, MINOR, MICRO, SUFFIX)
......@@ -106,14 +116,16 @@ if not release:
def do_setup():
write_version_py()
from setuptools import setup, find_packages
setup(name=NAME,
version=VERSION,
description=DESCRIPTION,
long_description=LONG_DESCRIPTION,
classifiers=CLASSIFIERS,
author=AUTHOR,
author_email=AUTHOR_EMAIL,
url=URL,
license=LICENSE,
platforms=PLATFORMS,
packages=find_packages(),
install_requires=['numpy>=1.3.0', 'scipy>=0.7.0'],
package_data={
......
......@@ -110,7 +110,4 @@ try:
import theano.version
__version__ = theano.version.version
except ImportError:
import warnings
warnings.warn(
"version.py could not be imported. Run setup.py at least once to generate it"
)
__version__ = "unknown"
import atexit, gc, os, stat
import atexit, os, stat
from theano.compile import optdb
from theano import config
......@@ -96,9 +96,6 @@ if cuda_available:
cuda_initialization_error_message = ""
# actively closing our gpu session presents segfault-on-exit on some systems
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:
cuda_available = False
cuda_initialization_error_message = e.message
......
......@@ -12,11 +12,43 @@
//If true, we fill with NAN allocated device memory.
#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
/////////////////////////
/**
*
* In the test program I'm using, the _outstanding_mallocs decreases with every call.
......@@ -48,6 +80,9 @@ void * device_malloc(size_t size)
return 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
for(int i=0;i<TABLE_SIZE;i++){
if(NULL==_alloc_size_table[i].ptr){
......@@ -81,6 +116,9 @@ int device_free(void *ptr)
return -1;
}
_outstanding_mallocs[0] -= (ptr != NULL);
if(ptr != NULL) {
gpu_context_decref();
}
#if COMPUTE_GPU_MEM_USED
int i=0;
for(;i<TABLE_SIZE;i++)
......@@ -1888,7 +1926,7 @@ CudaNdarray_gpu_init(PyObject* _unused, PyObject* args)
PyObject *
CudaNdarray_gpu_shutdown(PyObject* _unused, PyObject* _unused_args) {
cudaThreadExit();
gpu_context_decref();
Py_INCREF(Py_None);
return Py_None;
}
......
......@@ -812,8 +812,8 @@ def test_shared_float32():
del theano.shared.constructors[-1]
import theano.tensor.tests.test_basic
test_shared_options = theano.tensor.tests.test_basic.makeSharedTester(
import theano.tensor.tests.test_sharedvar
test_shared_options = theano.tensor.tests.test_sharedvar.makeSharedTester(
tcn.shared_constructor, 'float32', False, False, False,
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
from theano.tests import unittest_tools as utt
from theano import tensor
from theano.tensor.basic import _allclose
def eval_outputs(outputs):
......@@ -298,7 +299,7 @@ class test_structureddot(unittest.TestCase):
scipy_result = spmat * mat
assert theano_result.shape == scipy_result.shape
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):
......@@ -440,8 +441,8 @@ class test_structureddot(unittest.TestCase):
self.failUnless(numpy.allclose(theano_result, scipy_result))
self.failIf(theano_time > overhead_rtol*scipy_time + overhead_tol)
import theano.tensor.tests.test_basic
test_shared_options=theano.tensor.tests.test_basic.makeSharedTester(
import theano.tensor.tests.test_sharedvar
test_shared_options=theano.tensor.tests.test_sharedvar.makeSharedTester(
theano.sparse.shared, 'float64',
True, True, True, scipy.sparse.csc_matrix, scipy.sparse.issparse,
lambda a: dense_from_sparse(a*2.),
......
......@@ -321,6 +321,11 @@ def _allclose(a, b):
else:
atol = float64_atol
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)
def get_constant_value(v):
......
......@@ -3440,202 +3440,6 @@ def test_dimshuffle_duplicate():
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 1:
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 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论