mirror of
https://github.com/pytorch/pytorch.git
synced 2025-10-20 21:14:14 +08:00
* Change cpp_extensions.py to make it work on Windows * Fix linting * Show python paths * Debug * Debug 1 * set PYTHONPATH * Add ATen into library * expose essential libs and functions, and copy _C.lib * Specify dir in header * Update check_abi for MSVC * Activate cl environment to compile cpp extensions * change version string * Redirect stderr to stdout * Add monkey patch for windows * Remove unnecessary self * Fix various issues * Append necessary flags * add /MD flag to cuda * Install ninja * Use THP_API instead of THP_CLASS * Beautify the paths * Revert "Use THP_API instead of THP_CLASS" This reverts commit dd7e74c44db48e4c5f85bb8e3c698ff9de71ba2d. * Use THP_API instead of THP_CLASS(new)
257 lines
7.7 KiB
Python
257 lines
7.7 KiB
Python
#!/usr/bin/env python
|
|
|
|
from __future__ import print_function
|
|
|
|
import argparse
|
|
import os
|
|
import shlex
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
|
|
import torch
|
|
|
|
TESTS = [
|
|
'autograd',
|
|
'cpp_extensions',
|
|
'cuda',
|
|
'dataloader',
|
|
'distributed',
|
|
'distributions',
|
|
'indexing',
|
|
'jit',
|
|
'legacy_nn',
|
|
'multiprocessing',
|
|
'nccl',
|
|
'nn',
|
|
'optim',
|
|
'sparse',
|
|
'torch',
|
|
'utils',
|
|
]
|
|
|
|
WINDOWS_BLACKLIST = [
|
|
'distributed',
|
|
]
|
|
|
|
DISTRIBUTED_TESTS_CONFIG = {
|
|
'tcp': {
|
|
'WORLD_SIZE': '3'
|
|
},
|
|
'gloo': {
|
|
'WORLD_SIZE': '2' if torch.cuda.device_count() == 2 else '3'
|
|
},
|
|
'nccl': {
|
|
'WORLD_SIZE': '2'
|
|
},
|
|
'mpi': {},
|
|
}
|
|
|
|
|
|
def print_to_stderr(message):
|
|
print(message, file=sys.stderr)
|
|
|
|
|
|
def shell(command, cwd):
|
|
sys.stdout.flush()
|
|
sys.stderr.flush()
|
|
return subprocess.call(
|
|
shlex.split(command), universal_newlines=True, cwd=cwd) == 0
|
|
|
|
|
|
def get_shell_output(command):
|
|
return subprocess.check_output(shlex.split(command)).decode().strip()
|
|
|
|
|
|
def run_test(python, test_module, test_directory, options):
|
|
verbose = '--verbose' if options.verbose else ''
|
|
return shell('{} {} {}'.format(python, test_module, verbose),
|
|
test_directory)
|
|
|
|
|
|
def test_cpp_extensions(python, test_module, test_directory, options):
|
|
if not shell('{} setup.py install --root ./install'.format(python),
|
|
os.path.join(test_directory, 'cpp_extensions')):
|
|
return False
|
|
|
|
python_path = os.environ.get('PYTHONPATH', '')
|
|
try:
|
|
cpp_extensions = os.path.join(test_directory, 'cpp_extensions')
|
|
if sys.platform == 'win32':
|
|
install_directory = os.path.join(cpp_extensions, 'install')
|
|
install_directories = get_shell_output(
|
|
"where -r \"{}\" *.pyd".format(install_directory)).split('\r\n')
|
|
|
|
assert install_directories, 'install_directory must not be empty'
|
|
|
|
if len(install_directories) >= 1:
|
|
install_directory = install_directories[0]
|
|
|
|
install_directory = os.path.dirname(install_directory)
|
|
split_char = ';'
|
|
else:
|
|
install_directory = get_shell_output(
|
|
"find {}/install -name *-packages".format(cpp_extensions))
|
|
split_char = ':'
|
|
|
|
assert install_directory, 'install_directory must not be empty'
|
|
install_directory = os.path.join(test_directory, install_directory)
|
|
os.environ['PYTHONPATH'] = '{}{}{}'.format(install_directory,
|
|
split_char,
|
|
python_path)
|
|
return run_test(python, test_module, test_directory, options)
|
|
finally:
|
|
os.environ['PYTHONPATH'] = python_path
|
|
|
|
|
|
def test_distributed(python, test_module, test_directory, options):
|
|
mpi_available = subprocess.call('command -v mpiexec', shell=True) == 0
|
|
if options.verbose and not mpi_available:
|
|
print_to_stderr(
|
|
'MPI not available -- MPI backend tests will be skipped')
|
|
for backend, env_vars in DISTRIBUTED_TESTS_CONFIG.items():
|
|
if backend == 'mpi' and not mpi_available:
|
|
continue
|
|
for with_init_file in {True, False}:
|
|
tmp_dir = tempfile.mkdtemp()
|
|
if options.verbose:
|
|
with_init = ' with file init_method' if with_init_file else ''
|
|
print_to_stderr(
|
|
'Running distributed tests for the {} backend{}'.format(
|
|
backend, with_init))
|
|
os.environ['TEMP_DIR'] = tmp_dir
|
|
os.environ['BACKEND'] = backend
|
|
os.environ['INIT_METHOD'] = 'env://'
|
|
os.environ.update(env_vars)
|
|
if with_init_file:
|
|
init_method = 'file://{}/shared_init_file'.format(tmp_dir)
|
|
os.environ['INIT_METHOD'] = init_method
|
|
try:
|
|
os.mkdir(os.path.join(tmp_dir, 'barrier'))
|
|
os.mkdir(os.path.join(tmp_dir, 'test_dir'))
|
|
if backend == 'mpi':
|
|
mpiexec = 'mpiexec -n 3 --noprefix {}'.format(python)
|
|
if not run_test(mpiexec, test_module, test_directory,
|
|
options):
|
|
return False
|
|
elif not run_test(python, test_module, test_directory,
|
|
options):
|
|
return False
|
|
finally:
|
|
shutil.rmtree(tmp_dir)
|
|
return True
|
|
|
|
|
|
CUSTOM_HANDLERS = {
|
|
'cpp_extensions': test_cpp_extensions,
|
|
'distributed': test_distributed,
|
|
}
|
|
|
|
|
|
def parse_args():
|
|
parser = argparse.ArgumentParser(
|
|
description='Run the PyTorch unit test suite',
|
|
epilog='where TESTS is any of: {}'.format(', '.join(TESTS)))
|
|
parser.add_argument(
|
|
'-v',
|
|
'--verbose',
|
|
action='store_true',
|
|
help='print verbose information and test-by-test results')
|
|
parser.add_argument(
|
|
'-p', '--python', help='the python interpreter to execute tests with')
|
|
parser.add_argument(
|
|
'-c', '--coverage', action='store_true', help='enable coverage')
|
|
parser.add_argument(
|
|
'-i',
|
|
'--include',
|
|
nargs='+',
|
|
choices=TESTS,
|
|
default=TESTS,
|
|
metavar='TESTS',
|
|
help='select a set of tests to include (defaults to ALL tests)')
|
|
parser.add_argument(
|
|
'-x',
|
|
'--exclude',
|
|
nargs='+',
|
|
choices=TESTS,
|
|
metavar='TESTS',
|
|
default=[],
|
|
help='select a set of tests to exclude')
|
|
parser.add_argument(
|
|
'-f',
|
|
'--first',
|
|
choices=TESTS,
|
|
metavar='TESTS',
|
|
help='select the test to start from (excludes previous tests)')
|
|
parser.add_argument(
|
|
'-l',
|
|
'--last',
|
|
choices=TESTS,
|
|
metavar='TESTS',
|
|
help='select the last test to run (excludes following tests)')
|
|
parser.add_argument(
|
|
'--ignore-win-blacklist',
|
|
action='store_true',
|
|
help='always run blacklisted windows tests')
|
|
return parser.parse_args()
|
|
|
|
|
|
def get_python_command(options):
|
|
if options.coverage:
|
|
return 'coverage run --parallel-mode --source torch'
|
|
elif options.python:
|
|
return options.python
|
|
else:
|
|
return os.environ.get('PYCMD', 'python')
|
|
|
|
|
|
def get_selected_tests(options):
|
|
selected_tests = options.include
|
|
for test in options.exclude:
|
|
if test in selected_tests:
|
|
selected_tests.remove(test)
|
|
|
|
if options.first:
|
|
first_index = selected_tests.index(options.first)
|
|
selected_tests = selected_tests[first_index:]
|
|
|
|
if options.last:
|
|
last_index = selected_tests.index(options.last)
|
|
selected_tests = selected_tests[:last_index + 1]
|
|
|
|
if sys.platform == 'win32' and not options.ignore_win_blacklist:
|
|
for test in WINDOWS_BLACKLIST:
|
|
if test in selected_tests:
|
|
print_to_stderr('Excluding {} on Windows'.format(test))
|
|
selected_tests.remove(test)
|
|
|
|
return selected_tests
|
|
|
|
|
|
def main():
|
|
options = parse_args()
|
|
python = get_python_command(options)
|
|
test_directory = os.path.dirname(os.path.abspath(__file__))
|
|
selected_tests = get_selected_tests(options)
|
|
if options.verbose:
|
|
print_to_stderr('Selected tests: {}'.format(', '.join(selected_tests)))
|
|
|
|
if options.coverage:
|
|
shell('coverage erase')
|
|
|
|
for test in selected_tests:
|
|
test_module = 'test_{}.py'.format(test)
|
|
print_to_stderr('Running {} ...'.format(test_module))
|
|
handler = CUSTOM_HANDLERS.get(test, run_test)
|
|
if not handler(python, test_module, test_directory, options):
|
|
raise RuntimeError('{} failed!'.format(test_module))
|
|
|
|
if options.coverage:
|
|
shell('coverage combine')
|
|
shell('coverage html')
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|