提交 6c0f23db authored 作者: notoraptor's avatar notoraptor

Update tests script.

Add a script to quickly run specific tests.
上级 ef9095f9
...@@ -122,27 +122,34 @@ class CuDNNV51(object): ...@@ -122,27 +122,34 @@ class CuDNNV51(object):
# empty list of enum to don't crash with cudnn 5 # empty list of enum to don't crash with cudnn 5
cudnnReduceTensorOp_t = CEnumType() cudnnReduceTensorOp_t = CEnumType()
def get_supported_dtype_configs(self): def get_supported_dtype_configs(self, check_runtime=None):
""" """
Return the tuple of data type configurations supported by this version of cuDNN. Return the tuple of data type configurations supported by this version of cuDNN.
This is currently convenient for both cuDNN V5.1 and V6, as Theano does not This is currently convenient for both cuDNN V5.1 and V6, as Theano does not
yet support new data types (like INT8, INT8x4, etc.). yet support new data types (like INT8, INT8x4, etc.).
``check_runtime`` may be a function that tests if a data type configuration is supported.::
is_supported = check_runtime(dtype, precision)
.. warning::
From documentation for cudnnConvolutionForward (for both v5.1 and v6):
.. code-block::
TRUE_HALF_CONFIG is only supported on architectures with true fp16 support
(compute capability 5.3 and 6.0)
This seems to be a general remark about f16 support (not only for FWD).
It can be checked at runtime only.
""" """
return (TRUE_HALF_CONFIG, PSEUDO_HALF_CONFIG, FLOAT_CONFIG, DOUBLE_CONFIG)
def get_fwd_dtype_configs(self, check_runtime=None):
# NB: "TRUE_HALF_CONFIG is only supported on architectures with true fp16 support
# (compute capability 5.3 and 6.0)". Can be checked at runtime only.
if check_runtime is None or check_runtime(*TRUE_HALF_CONFIG): if check_runtime is None or check_runtime(*TRUE_HALF_CONFIG):
return self.get_supported_dtype_configs() return (TRUE_HALF_CONFIG, PSEUDO_HALF_CONFIG, FLOAT_CONFIG, DOUBLE_CONFIG)
return (PSEUDO_HALF_CONFIG, FLOAT_CONFIG, DOUBLE_CONFIG) return (PSEUDO_HALF_CONFIG, FLOAT_CONFIG, DOUBLE_CONFIG)
def get_bwd_filter_dtype_configs(self, check_runtime=None):
return self.get_supported_dtype_configs()
def get_bwd_data_dtype_configs(self, check_runtime=None):
return self.get_supported_dtype_configs()
def fwd_algo_supports_dtype_config(self, algo, dtype, precision, ndim): def fwd_algo_supports_dtype_config(self, algo, dtype, precision, ndim):
algorithms = self.cudnnConvolutionFwdAlgo_t algorithms = self.cudnnConvolutionFwdAlgo_t
algo = algorithms.fromalias(algo) algo = algorithms.fromalias(algo)
...@@ -209,7 +216,7 @@ class CuDNNV51(object): ...@@ -209,7 +216,7 @@ class CuDNNV51(object):
if ndim == 3: if ndim == 3:
return not is_true_half_config(dtype, precision) return not is_true_half_config(dtype, precision)
if algo == algorithms.CUDNN_CONVOLUTION_BWD_DATA_ALGO_WINOGRAD: if algo == algorithms.CUDNN_CONVOLUTION_BWD_DATA_ALGO_WINOGRAD:
return ndim == 2 and is_pseudo_half_config(dtype, precision) or is_float_config(dtype, precision) return ndim == 2 and (is_pseudo_half_config(dtype, precision) or is_float_config(dtype, precision))
if algo == algorithms.CUDNN_CONVOLUTION_BWD_DATA_ALGO_WINOGRAD_NONFUSED: if algo == algorithms.CUDNN_CONVOLUTION_BWD_DATA_ALGO_WINOGRAD_NONFUSED:
# NB: "If wDesc 's filter (height, width) is (5,5), data type config TRUE_HALF_CONFIG is not supported". # NB: "If wDesc 's filter (height, width) is (5,5), data type config TRUE_HALF_CONFIG is not supported".
# We could not check it before being in C code. # We could not check it before being in C code.
......
# This script allows to run one specific cuDNN convolution test case.
# python run_dnn_conv.py --help # Print help.
# python run_dnn_conv.py {fwd|bwd-filter|bwd-data} {2d|3d} -a <algo> -i <inputShape> -f <filterShape> ...
from __future__ import absolute_import, print_function, division
import argparse
import sys
import theano
from theano.configdefaults import SUPPORTED_DNN_CONV_ALGO_RUNTIME
from theano.gpuarray.cudnn_defs import (HALF, FLOAT, DOUBLE,
TRUE_HALF_CONFIG, PSEUDO_HALF_CONFIG, FLOAT_CONFIG, DOUBLE_CONFIG)
from theano.gpuarray.tests.check_dnn_conv import (cudnn, TestDnnConv2D, TestDnnConv3D, CheckDnn)
class TupleAction(argparse.Action):
# Tuple extractor for command line args parser.
def __call__(self, parser, namespace, values, option_string=None):
values = tuple(int(v) for v in values.split(','))
setattr(namespace, self.dest, values)
class BorderAction(TupleAction):
# Border extractor for command line args parser.
def __call__(self, parser, namespace, values, option_string=None):
if values not in ('valid', 'full', 'half'):
super(BorderAction, self).__call__(parser, namespace, values, option_string)
else:
setattr(namespace, self.dest, values)
if __name__ != '__main__':
raise ImportError('This script cannot be imported.')
args = sys.argv[1:]
computations = FWD, BWD_FILTER, BWD_DATA = ('fwd', 'gradweight', 'gradinput')
dimensions = ('2D', '2d', '3D', '3d')
algorithms = (tuple(sorted(list(set(cudnn.cudnnConvolutionFwdAlgo_t.get_aliases() +
cudnn.cudnnConvolutionBwdFilterAlgo_t.get_aliases() +
cudnn.cudnnConvolutionBwdDataAlgo_t.get_aliases())))) +
SUPPORTED_DNN_CONV_ALGO_RUNTIME)
types = (HALF, FLOAT, DOUBLE)
data_type_configurations = dict(TRUE_HALF_CONFIG=TRUE_HALF_CONFIG, PSEUDO_HALF_CONFIG=PSEUDO_HALF_CONFIG,
FLOAT_CONFIG=FLOAT_CONFIG, DOUBLE_CONFIG=DOUBLE_CONFIG)
parser = argparse.ArgumentParser()
parser.add_argument('computation', choices=computations,
help='Computation to run.')
parser.add_argument('ndim', choices=dimensions,
help='Number of dimensions ("2D" or "3D", case insensitive).')
parser.add_argument('-a', '--algo', choices=algorithms, required=True,
help='Algorithm to use for computation.')
parser.add_argument('-i', '--input-shape', action=TupleAction, required=True,
help='Input shape. Comma-separated list of integers (no spaces).')
parser.add_argument('-f', '--filter-shape', action=TupleAction, required=True,
help='Filter shape. Comma-separated list of integers (no spaces).')
parser.add_argument('-D', '--dtype-config', choices=list(sorted(data_type_configurations.keys())), default=None,
help='Data type configuration for (data type; precision). Default (theano floatX; theano floatX). '
'To specify data type configuration, you can either use this option or set data type and '
'precision separately with "-t" and "-p" options.')
parser.add_argument('-t', '--dtype', choices=types, default=None,
help='Data type (default theano floatX).')
parser.add_argument('-p', '--precision', choices=types, default=None,
help='Precision (default theano floatX).')
parser.add_argument('-s', '--subsample', action=TupleAction,
help='Subsample. Comma-separated list of integers (no spaces). '
'Default: 1 per dimension.')
parser.add_argument('-d', '--dilation', action=TupleAction,
help='Dilation. Comma-separated list of integers (no spaces). '
'Default: 1 per dimension.')
parser.add_argument('-b', '--border-mode', default='valid', action=BorderAction,
help='Border mode. "valid" (default), "full", "half" '
'or a comma-separated list of integers (no spaces).')
parser.add_argument('-c', '--conv-mode', choices=('conv', 'cross'), default='conv',
help='Conv mode (default: conv).')
parser.add_argument('-A', '--alpha', type=float, default=1,
help="alpha (floating), must not be zero. Default 1.")
parser.add_argument('-B', '--beta', type=float, default=0,
help='beta (floating). Default 0.')
parser.add_argument('-I', '--print-infos', action='store_true', default=False,
help='Print some infos before testing.')
args = parser.parse_args(args)
test = args.computation
ndim = int(args.ndim[0])
if ndim == 2:
tests = TestDnnConv2D()
if ndim == 3:
tests = TestDnnConv3D()
if args.subsample is None:
args.subsample = (1,) * ndim
if args.dilation is None:
args.dilation = (1,) * ndim
if not (ndim == len(args.input_shape[2:]) == len(args.filter_shape[2:]) == len(args.subsample) == len(
args.dilation)):
raise ValueError('Expected parameters sized for %d dimensions.' % ndim)
if isinstance(args.border_mode, tuple) and ndim != len(args.border_mode):
raise ValueError('Expected borders sized for %d dimensions.' % ndim)
if args.alpha == 0:
raise ValueError('Nothing could be computed if alpha is 0.')
if args.dtype_config is None:
if args.dtype is None:
args.dtype = theano.config.floatX
if args.precision is None:
args.precision = theano.config.floatX
else:
if args.dtype is not None or args.precision is not None:
raise ValueError('You must specify either -D <data-type-configuration> '
'or (-t <data-type> -p <precision>), not both.')
args.dtype, args.precision = data_type_configurations[args.dtype_config]
if (args.dtype, args.precision) not in cudnn.get_supported_dtype_configs():
raise ValueError('Unsupported data type configuration %s %s.' % (args.dtype, args.precision))
if args.algo not in SUPPORTED_DNN_CONV_ALGO_RUNTIME:
check_config = False
if test == FWD:
check_config = cudnn.fwd_algo_supports_dtype_config(args.algo, args.dtype, args.precision, ndim)
if test == BWD_FILTER:
check_config = cudnn.bwd_filter_algo_supports_dtype_config(args.algo, args.dtype, args.precision, ndim)
if test == BWD_DATA:
check_config = cudnn.bwd_data_algo_supports_dtype_config(args.algo, args.dtype, args.precision, ndim)
if not check_config:
raise ValueError('%s computation does not support configuration (%s, %s) for algo %s.' % (
test, args.dtype, args.precision, args.algo))
algo = args.algo
dtype = args.dtype
precision = args.precision
parameters = (
args.input_shape, args.filter_shape, args.subsample, args.dilation, args.border_mode, args.conv_mode,
args.alpha, args.beta)
if args.print_infos:
CheckDnn.print_infos(count_tests=False)
print('======================')
print('Running', test, algo, dtype, precision, *parameters)
if test == FWD:
tests.run_conv_fwd(algo, dtype, precision, parameters)
if test == BWD_FILTER:
tests.run_conv_gradweight(algo, dtype, precision, parameters)
if test == BWD_DATA:
tests.run_conv_gradinput(algo, dtype, precision, parameters)
print('... OK')
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论