blob: 21d925947cec8c5d4a029434b28fbfaa9e6bb7c9 [file] [log] [blame]
Phoenix Meadowlarkbe1589d2020-10-06 21:48:40 -07001#!/usr/bin/env python3
2
3# Copyright 2020 Google LLC
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# https://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16"""Runs all E2E TensorFlow tests and extracts their benchmarking artifacts.
17
Phoenix Meadowlarkab21d2a2020-10-23 09:30:43 -070018Example usages:
19 # Run all test suites and collect their artifacts:
20 python3 ./scripts/get_e2e_artifacts.py
21
22 # Run the e2e_tests test suite and collect its artifacts:
23 python3 ./scripts/get_e2e_artifacts.py --test_suites=e2e_tests
Phoenix Meadowlarkbe1589d2020-10-06 21:48:40 -070024"""
25
26import fileinput
27import os
28import re
29import subprocess
30import tempfile
31from typing import Dict, Set
32import zipfile
33
34import utils
35
36from absl import app
37from absl import flags
38
39SUITE_NAME_TO_TARGET = {
40 'e2e_tests':
41 '//integrations/tensorflow/e2e:e2e_tests',
42 'mobile_bert_squad_tests':
43 '//integrations/tensorflow/e2e:mobile_bert_squad_tests',
Phoenix Meadowlarkab4cb7c2020-11-06 15:03:30 -080044 'layers_tests':
45 '//integrations/tensorflow/e2e/keras/layers:layers_tests',
46 'layers_dynamic_batch_tests':
47 '//integrations/tensorflow/e2e/keras/layers:layers_dynamic_batch_tests',
48 'layers_training_tests':
49 '//integrations/tensorflow/e2e/keras/layers:layers_training_tests',
Phoenix Meadowlarka4ee4ff2020-11-05 10:42:36 -080050 'keyword_spotting_tests':
51 '//integrations/tensorflow/e2e/keras:keyword_spotting_tests',
52 'keyword_spotting_internal_streaming_tests':
53 '//integrations/tensorflow/e2e/keras:keyword_spotting_internal_streaming_tests',
Phoenix Meadowlark8c8b9722020-10-28 11:26:45 -070054 'imagenet_non_hermetic_tests':
Phoenix Meadowlark1f86f0e2020-12-01 14:42:32 -080055 '//integrations/tensorflow/e2e/keras/applications:imagenet_non_hermetic_tests',
Phoenix Meadowlarkab21d2a2020-10-23 09:30:43 -070056 'slim_vision_tests':
57 '//integrations/tensorflow/e2e/slim_vision_models:slim_vision_tests',
Phoenix Meadowlarkbe1589d2020-10-06 21:48:40 -070058}
59SUITES_HELP = [f'`{name}`' for name in SUITE_NAME_TO_TARGET]
60SUITES_HELP = f'{", ".join(SUITES_HELP[:-1])} and {SUITES_HELP[-1]}'
61
62FLAGS = flags.FLAGS
63
64flags.DEFINE_bool(
65 'dry_run', False,
66 'Run without extracting files. Useful for quickly checking for artifact '
67 'collisions.')
68flags.DEFINE_string(
69 'artifacts_dir', os.path.join(tempfile.gettempdir(), 'iree', 'modules'),
70 'Directory to transfer the benchmarking artifacts to. Defaults to '
71 '/tmp/iree/modules/')
72flags.DEFINE_bool('run_test_suites', True, 'Run any specified test suites.')
73flags.DEFINE_list('test_suites', list(SUITE_NAME_TO_TARGET.keys()),
74 f'Any combination of {SUITES_HELP}.')
75
76EXPECTED_COLLISIONS = [
77 '/tf_ref/', 'tf_input.mlir', 'iree_input.mlir', '/saved_model/'
78]
79
80
81def _target_to_testlogs_path(target: str) -> str:
82 """Convert target into the path where Bazel stores the artifacts we want."""
83 return os.path.join('bazel-testlogs',
84 target.replace('//', '').replace(':', os.sep))
85
86
87def _target_to_test_name(target: str, test_suite_path: str) -> str:
88 """Get test_name from `suite_name_test_name__tf__backend_name`."""
89 return target.split('__')[0].replace(f'{test_suite_path}_', '')
90
91
92def get_test_paths_and_names(test_suite_path: str):
93 """Get the paths Bazel stores test outputs in and the matching test names."""
94 targets = utils.get_test_targets(test_suite_path)
95 test_paths = [_target_to_testlogs_path(target) for target in targets]
96 test_names = [
97 _target_to_test_name(target, test_suite_path) for target in targets
98 ]
99 return test_paths, test_names
100
101
102def check_collision(filename: str, test_name: str, written_paths: Set[str],
103 paths_to_tests: Dict[str, str]):
104 """Check that we aren't overwriting files unless we expect to."""
105 # Note: We can't use a check that the files have identical contents because
106 # tf_input.mlir can have random numbers appended to its function names.
107 # See https://github.com/google/iree/issues/3375
108
109 expected_collision = any([name in filename for name in EXPECTED_COLLISIONS])
110 if filename in written_paths and not expected_collision:
111 raise ValueError(f'Collision found on {filename} between {test_name}.py '
112 f'and {paths_to_tests[filename]}.py')
113 else:
114 written_paths.add(filename)
115 paths_to_tests[filename] = test_name
116
117
118def update_path(archive_path: str):
Phoenix Meadowlark3d8e9ca2020-10-12 14:29:32 -0700119 """Update the --module_file flag with the new location of the compiled.vmfb"""
Phoenix Meadowlarkbe1589d2020-10-06 21:48:40 -0700120 backend_path = archive_path.split('traces')[0] # 'ModuleName/backend_name'.
121 compiled_path = os.path.join(FLAGS.artifacts_dir, backend_path,
122 'compiled.vmfb')
123 flagfile_path = os.path.join(FLAGS.artifacts_dir, archive_path)
124 for line in fileinput.input(files=[flagfile_path], inplace=True):
Phoenix Meadowlark3d8e9ca2020-10-12 14:29:32 -0700125 if line.strip().startswith('--module_file'):
126 print(f'--module_file={compiled_path}\n', end='')
Phoenix Meadowlarkbe1589d2020-10-06 21:48:40 -0700127 else:
128 print(line, end='')
129
130
131def extract_artifacts(test_path: str, test_name: str, written_paths: Set[str],
132 paths_to_tests: Dict[str, str]):
133 """Unzips all of the benchmarking artifacts for a given test and backend."""
134 outputs = os.path.join(test_path, 'test.outputs', 'outputs.zip')
Phoenix Meadowlarkab21d2a2020-10-23 09:30:43 -0700135 if FLAGS.dry_run and not os.path.exists(outputs):
136 # The artifacts may or may not be present on disk during a dry run. If they
137 # are then we want to collision check them, but if they aren't that's fine.
138 return
139
Phoenix Meadowlarkbe1589d2020-10-06 21:48:40 -0700140 archive = zipfile.ZipFile(outputs)
141 # Filter out directory names.
142 filenames = [name for name in archive.namelist() if name[-1] != os.sep]
143
144 for filename in filenames:
145 # Check for collisions.
146 check_collision(filename, test_name, written_paths, paths_to_tests)
147
148 # Extract and update flagfile path.
149 if not FLAGS.dry_run:
150 archive.extract(filename, FLAGS.artifacts_dir)
151 if filename.endswith('flagfile'):
152 update_path(filename)
153
154
155def main(argv):
156 del argv # Unused.
157
158 # Convert test suite shorthands to full test suite targets.
159 test_suites = [SUITE_NAME_TO_TARGET[suite] for suite in FLAGS.test_suites]
160
Phoenix Meadowlarkab21d2a2020-10-23 09:30:43 -0700161 if FLAGS.run_test_suites:
162 # Use bazel test to execute all of the test suites in parallel.
Phoenix Meadowlark589dfa72020-11-21 20:19:52 -0800163 command = ['bazel', 'test', *test_suites, '--color=yes']
Phoenix Meadowlarkab21d2a2020-10-23 09:30:43 -0700164 print(f'Running: `{" ".join(command)}`')
165 if not FLAGS.dry_run:
166 subprocess.check_call(command)
167 print()
168
Phoenix Meadowlarkbe1589d2020-10-06 21:48:40 -0700169 written_paths = set()
170 paths_to_tests = dict()
171
172 for test_suite in test_suites:
Phoenix Meadowlarkbe1589d2020-10-06 21:48:40 -0700173 # Extract all of the artifacts for this test suite.
174 test_paths, test_names = get_test_paths_and_names(test_suite)
175 for i, (test_path, test_name) in enumerate(zip(test_paths, test_names)):
176 print(f'\rTransfering {test_suite} {i + 1}/{len(test_paths)}', end='')
177 extract_artifacts(test_path, test_name, written_paths, paths_to_tests)
178 print('\n')
179
180
181if __name__ == '__main__':
182 app.run(main)