Skip to content

Commit 0d03e73

Browse files
authored
Merge pull request #3 from gchanan/testing_the_thing
[TESTING THE THING] Testing the thing
2 parents d2472d1 + 858e0c5 commit 0d03e73

File tree

7,340 files changed

+1220191
-159933
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

7,340 files changed

+1220191
-159933
lines changed

.circleci/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
*.svg
2+
*.png

.circleci/README.md

Lines changed: 504 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
"""
2+
This module models the tree of configuration variants
3+
for "smoketest" builds.
4+
5+
Each subclass of ConfigNode represents a layer of the configuration hierarchy.
6+
These tree nodes encapsulate the logic for whether a branch of the hierarchy
7+
should be "pruned".
8+
9+
In addition to generating config.yml content, the tree is also traversed
10+
to produce a visualization of config dimensions.
11+
"""
12+
13+
from collections import OrderedDict
14+
15+
from cimodel.lib.conf_tree import ConfigNode
16+
import cimodel.data.dimensions as dimensions
17+
18+
19+
LINKING_DIMENSIONS = [
20+
"shared",
21+
"static",
22+
]
23+
24+
25+
DEPS_INCLUSION_DIMENSIONS = [
26+
"with-deps",
27+
"without-deps",
28+
]
29+
30+
31+
def get_processor_arch_name(cuda_version):
32+
return "cpu" if not cuda_version else "cu" + cuda_version
33+
34+
35+
LINUX_PACKAGE_VARIANTS = OrderedDict(
36+
manywheel=[
37+
"2.7m",
38+
"2.7mu",
39+
"3.5m",
40+
"3.6m",
41+
"3.7m",
42+
],
43+
conda=dimensions.STANDARD_PYTHON_VERSIONS,
44+
libtorch=[
45+
"2.7m",
46+
],
47+
)
48+
49+
CONFIG_TREE_DATA = OrderedDict(
50+
linux=(dimensions.CUDA_VERSIONS, LINUX_PACKAGE_VARIANTS),
51+
macos=([None], OrderedDict(
52+
wheel=dimensions.STANDARD_PYTHON_VERSIONS,
53+
conda=dimensions.STANDARD_PYTHON_VERSIONS,
54+
libtorch=[
55+
"2.7",
56+
],
57+
)),
58+
)
59+
60+
# GCC config variants:
61+
#
62+
# All the nightlies (except libtorch with new gcc ABI) are built with devtoolset7,
63+
# which can only build with old gcc ABI. It is better than devtoolset3
64+
# because it understands avx512, which is needed for good fbgemm performance.
65+
#
66+
# Libtorch with new gcc ABI is built with gcc 5.4 on Ubuntu 16.04.
67+
LINUX_GCC_CONFIG_VARIANTS = OrderedDict(
68+
manywheel=['devtoolset7'],
69+
conda=['devtoolset7'],
70+
libtorch=[
71+
"devtoolset7",
72+
"gcc5.4_cxx11-abi",
73+
],
74+
)
75+
76+
77+
class TopLevelNode(ConfigNode):
78+
def __init__(self, node_name, config_tree_data, smoke):
79+
super(TopLevelNode, self).__init__(None, node_name)
80+
81+
self.config_tree_data = config_tree_data
82+
self.props["smoke"] = smoke
83+
84+
def get_children(self):
85+
return [OSConfigNode(self, x, c, p) for (x, (c, p)) in self.config_tree_data.items()]
86+
87+
88+
class OSConfigNode(ConfigNode):
89+
def __init__(self, parent, os_name, cuda_versions, py_tree):
90+
super(OSConfigNode, self).__init__(parent, os_name)
91+
92+
self.py_tree = py_tree
93+
self.props["os_name"] = os_name
94+
self.props["cuda_versions"] = cuda_versions
95+
96+
def get_children(self):
97+
return [PackageFormatConfigNode(self, k, v) for k, v in self.py_tree.items()]
98+
99+
100+
class PackageFormatConfigNode(ConfigNode):
101+
def __init__(self, parent, package_format, python_versions):
102+
super(PackageFormatConfigNode, self).__init__(parent, package_format)
103+
104+
self.props["python_versions"] = python_versions
105+
self.props["package_format"] = package_format
106+
107+
def get_children(self):
108+
if self.find_prop("os_name") == "linux":
109+
return [LinuxGccConfigNode(self, v) for v in LINUX_GCC_CONFIG_VARIANTS[self.find_prop("package_format")]]
110+
else:
111+
return [ArchConfigNode(self, v) for v in self.find_prop("cuda_versions")]
112+
113+
114+
class LinuxGccConfigNode(ConfigNode):
115+
def __init__(self, parent, gcc_config_variant):
116+
super(LinuxGccConfigNode, self).__init__(parent, "GCC_CONFIG_VARIANT=" + str(gcc_config_variant))
117+
118+
self.props["gcc_config_variant"] = gcc_config_variant
119+
120+
def get_children(self):
121+
cuda_versions = self.find_prop("cuda_versions")
122+
123+
# XXX devtoolset7 on CUDA 9.0 is temporarily disabled
124+
# see https://github.com/pytorch/pytorch/issues/20066
125+
if self.find_prop("gcc_config_variant") == 'devtoolset7':
126+
cuda_versions = filter(lambda x: x != "90", cuda_versions)
127+
128+
return [ArchConfigNode(self, v) for v in cuda_versions]
129+
130+
131+
class ArchConfigNode(ConfigNode):
132+
def __init__(self, parent, cu):
133+
super(ArchConfigNode, self).__init__(parent, get_processor_arch_name(cu))
134+
135+
self.props["cu"] = cu
136+
137+
def get_children(self):
138+
return [PyVersionConfigNode(self, v) for v in self.find_prop("python_versions")]
139+
140+
141+
class PyVersionConfigNode(ConfigNode):
142+
def __init__(self, parent, pyver):
143+
super(PyVersionConfigNode, self).__init__(parent, pyver)
144+
145+
self.props["pyver"] = pyver
146+
147+
def get_children(self):
148+
149+
smoke = self.find_prop("smoke")
150+
package_format = self.find_prop("package_format")
151+
os_name = self.find_prop("os_name")
152+
153+
has_libtorch_variants = package_format == "libtorch" and os_name == "linux"
154+
linking_variants = LINKING_DIMENSIONS if has_libtorch_variants else []
155+
156+
return [LinkingVariantConfigNode(self, v) for v in linking_variants]
157+
158+
159+
class LinkingVariantConfigNode(ConfigNode):
160+
def __init__(self, parent, linking_variant):
161+
super(LinkingVariantConfigNode, self).__init__(parent, linking_variant)
162+
163+
def get_children(self):
164+
return [DependencyInclusionConfigNode(self, v) for v in DEPS_INCLUSION_DIMENSIONS]
165+
166+
167+
class DependencyInclusionConfigNode(ConfigNode):
168+
def __init__(self, parent, deps_variant):
169+
super(DependencyInclusionConfigNode, self).__init__(parent, deps_variant)
170+
171+
self.props["libtorch_variant"] = "-".join([self.parent.get_label(), self.get_label()])
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
from collections import OrderedDict
2+
3+
import cimodel.data.binary_build_data as binary_build_data
4+
import cimodel.lib.conf_tree as conf_tree
5+
import cimodel.lib.miniutils as miniutils
6+
7+
8+
class Conf(object):
9+
def __init__(self, os, cuda_version, pydistro, parms, smoke, libtorch_variant, gcc_config_variant):
10+
11+
self.os = os
12+
self.cuda_version = cuda_version
13+
self.pydistro = pydistro
14+
self.parms = parms
15+
self.smoke = smoke
16+
self.libtorch_variant = libtorch_variant
17+
self.gcc_config_variant = gcc_config_variant
18+
19+
def gen_build_env_parms(self):
20+
elems = [self.pydistro] + self.parms + [binary_build_data.get_processor_arch_name(self.cuda_version)]
21+
if self.gcc_config_variant is not None:
22+
elems.append(str(self.gcc_config_variant))
23+
return elems
24+
25+
def gen_docker_image(self):
26+
if self.gcc_config_variant == 'gcc5.4_cxx11-abi':
27+
return miniutils.quote("pytorch/pytorch-binary-docker-image-ubuntu16.04:latest")
28+
29+
docker_word_substitution = {
30+
"manywheel": "manylinux",
31+
"libtorch": "manylinux",
32+
}
33+
34+
docker_distro_prefix = miniutils.override(self.pydistro, docker_word_substitution)
35+
36+
# The cpu nightlies are built on the pytorch/manylinux-cuda100 docker image
37+
alt_docker_suffix = self.cuda_version or "100"
38+
docker_distro_suffix = "" if self.pydistro == "conda" else alt_docker_suffix
39+
return miniutils.quote("pytorch/" + docker_distro_prefix + "-cuda" + docker_distro_suffix)
40+
41+
def get_name_prefix(self):
42+
return "smoke" if self.smoke else "binary"
43+
44+
def gen_build_name(self, build_or_test, nightly):
45+
46+
parts = [self.get_name_prefix(), self.os] + self.gen_build_env_parms()
47+
48+
if nightly:
49+
parts.append("nightly")
50+
51+
if self.libtorch_variant:
52+
parts.append(self.libtorch_variant)
53+
54+
if not self.smoke:
55+
parts.append(build_or_test)
56+
57+
joined = "_".join(parts)
58+
return joined.replace(".", "_")
59+
60+
def gen_workflow_job(self, phase, upload_phase_dependency=None, nightly=False):
61+
job_def = OrderedDict()
62+
job_def["name"] = self.gen_build_name(phase, nightly)
63+
job_def["build_environment"] = miniutils.quote(" ".join(self.gen_build_env_parms()))
64+
job_def["requires"] = ["setup"]
65+
if self.smoke:
66+
job_def["requires"].append("update_s3_htmls_for_nightlies")
67+
job_def["requires"].append("update_s3_htmls_for_nightlies_devtoolset7")
68+
job_def["filters"] = {"branches": {"only": "postnightly"}}
69+
else:
70+
job_def["filters"] = {"branches": {"only": "nightly"}}
71+
if self.libtorch_variant:
72+
job_def["libtorch_variant"] = miniutils.quote(self.libtorch_variant)
73+
if phase == "test":
74+
if not self.smoke:
75+
job_def["requires"].append(self.gen_build_name("build", nightly))
76+
if not (self.smoke and self.os == "macos"):
77+
job_def["docker_image"] = self.gen_docker_image()
78+
79+
if self.cuda_version:
80+
job_def["use_cuda_docker_runtime"] = miniutils.quote("1")
81+
else:
82+
if self.os == "linux" and phase != "upload":
83+
job_def["docker_image"] = self.gen_docker_image()
84+
85+
if phase == "test":
86+
if self.cuda_version:
87+
job_def["resource_class"] = "gpu.medium"
88+
if phase == "upload":
89+
job_def["context"] = "org-member"
90+
job_def["requires"] = ["setup", self.gen_build_name(upload_phase_dependency, nightly)]
91+
92+
os_name = miniutils.override(self.os, {"macos": "mac"})
93+
job_name = "_".join([self.get_name_prefix(), os_name, phase])
94+
return {job_name : job_def}
95+
96+
def get_root(smoke, name):
97+
98+
return binary_build_data.TopLevelNode(
99+
name,
100+
binary_build_data.CONFIG_TREE_DATA,
101+
smoke,
102+
)
103+
104+
105+
def gen_build_env_list(smoke):
106+
107+
root = get_root(smoke, "N/A")
108+
config_list = conf_tree.dfs(root)
109+
110+
newlist = []
111+
for c in config_list:
112+
conf = Conf(
113+
c.find_prop("os_name"),
114+
c.find_prop("cu"),
115+
c.find_prop("package_format"),
116+
[c.find_prop("pyver")],
117+
c.find_prop("smoke"),
118+
c.find_prop("libtorch_variant"),
119+
c.find_prop("gcc_config_variant"),
120+
)
121+
newlist.append(conf)
122+
123+
return newlist
124+
125+
126+
def predicate_exclude_nonlinux_and_libtorch(config):
127+
return config.os == "linux"
128+
129+
130+
def get_nightly_uploads():
131+
configs = gen_build_env_list(False)
132+
mylist = []
133+
for conf in configs:
134+
phase_dependency = "test" if predicate_exclude_nonlinux_and_libtorch(conf) else "build"
135+
mylist.append(conf.gen_workflow_job("upload", phase_dependency, nightly=True))
136+
137+
return mylist
138+
139+
def get_nightly_tests():
140+
141+
configs = gen_build_env_list(False)
142+
filtered_configs = filter(predicate_exclude_nonlinux_and_libtorch, configs)
143+
144+
tests = []
145+
for conf_options in filtered_configs:
146+
yaml_item = conf_options.gen_workflow_job("test", nightly=True)
147+
tests.append(yaml_item)
148+
149+
return tests
150+
151+
152+
def get_jobs(toplevel_key, smoke):
153+
jobs_list = []
154+
configs = gen_build_env_list(smoke)
155+
phase = "build" if toplevel_key == "binarybuilds" else "test"
156+
for build_config in configs:
157+
jobs_list.append(build_config.gen_workflow_job(phase, nightly=True))
158+
159+
return jobs_list
160+
161+
162+
def get_binary_build_jobs():
163+
return get_jobs("binarybuilds", False)
164+
165+
166+
def get_binary_smoke_test_jobs():
167+
return get_jobs("binarysmoketests", True)

0 commit comments

Comments
 (0)