Skip to content

Commit 8e4cd34

Browse files
committed
Update on "[jit] register __getitem__ builtin"
[jit] register __getitem__ builtin Summary: Follow up of #21990, I am switching index select operations to a standard __getitem__ builtin, rather than bunch of different builtins according to the type, such as prim::DictIndex, prim::ListIndex, etc. This will also aligned with the some other magic methods that we already use gh-metadata: pytorch pytorch 22276 gh/wanchaol/28/head
2 parents 2ed6607 + ce8ac74 commit 8e4cd34

File tree

157 files changed

+4525
-1773
lines changed

Some content is hidden

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

157 files changed

+4525
-1773
lines changed

.jenkins/pytorch/common.sh

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ function cleanup {
1717

1818
set -ex
1919

20+
# Save the SCRIPT_DIR absolute path in case later we chdir (as occurs in the gpu perf test)
21+
SCRIPT_DIR="$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P )"
22+
2023
# Required environment variables:
2124
# $BUILD_ENVIRONMENT (should be set by your Docker image)
2225

@@ -89,7 +92,7 @@ if which sccache > /dev/null; then
8992
sccache --zero-stats
9093
function sccache_epilogue() {
9194
echo '=================== sccache compilation log ==================='
92-
python "$(dirname "${BASH_SOURCE[0]}")/print_sccache_log.py" ~/sccache_error.log
95+
python "$SCRIPT_DIR/print_sccache_log.py" ~/sccache_error.log 2>/dev/null
9396
echo '=========== If your build fails, please take a look at the log above for possible reasons ==========='
9497
sccache --show-stats
9598
sccache --stop-server || true

CMakeLists.txt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,12 @@ if(APPLE)
6262
set(CMAKE_MACOSX_RPATH ON)
6363
endif()
6464

65+
if (${CMAKE_HOST_SYSTEM_PROCESSOR} MATCHES "(x86_64|i[3-6]+86)")
66+
set(CPU_INTEL ON)
67+
else ()
68+
set(CPU_INTEL OFF)
69+
endif ()
70+
6571
# ---[ Options.
6672
# Note to developers: if you add an option below, make sure you also add it to
6773
# cmake/Summary.cmake so that the summary prints out the option values.
@@ -126,7 +132,10 @@ option(USE_SYSTEM_EIGEN_INSTALL
126132
option(USE_TENSORRT "Using Nvidia TensorRT library" OFF)
127133
option(USE_ZMQ "Use ZMQ" OFF)
128134
option(USE_ZSTD "Use ZSTD" OFF)
129-
option(USE_MKLDNN "Use MKLDNN" OFF)
135+
cmake_dependent_option(
136+
USE_MKLDNN "Use MKLDNN. Only available on x86 and x86_64." ON
137+
"CPU_INTEL" OFF)
138+
set(MKLDNN_ENABLE_CONCURRENT_EXEC ${USE_MKLDNN})
130139
option(USE_DISTRIBUTED "Use distributed" ON)
131140
cmake_dependent_option(
132141
USE_MPI "Use MPI for Caffe2. Only available if USE_DISTRIBUTED is on." ON

aten/re_worker_requirements

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"ATen-cpu#compile-THTensorMoreMath.cpp.oc1c23613,platform007-clang": {
3+
"workerSize": "MEDIUM",
4+
"platformType": "LINUX"
5+
},
6+
"ATen-cu#compile-pic-Unique.cu.o199e1a23,platform007-clang": {
7+
"workerSize": "MEDIUM",
8+
"platformType": "LINUX"
9+
}
10+
}

aten/src/ATen/Declarations.cwrap

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,8 @@
328328
[[
329329
name: _th_scatter_
330330
return: argument 0
331+
cpu_bool: True
332+
cuda_bool: True
331333
variants: function
332334
options:
333335
- cname: scatter
@@ -349,6 +351,8 @@
349351
name: _th_scatter_add_
350352
return: argument 0
351353
cname: scatterAdd
354+
cpu_bool: True
355+
cuda_bool: True
352356
variants: function
353357
arguments:
354358
- THTensor* self
@@ -360,6 +364,8 @@
360364
[[
361365
name: _th_gather
362366
cname: gather
367+
cpu_bool: True
368+
cuda_bool: True
363369
variants:
364370
- function
365371
return: argument 0

aten/src/ATen/Dimname.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ struct CAFFE2_API Dimname {
2020

2121
bool can_refer_to(const Dimname& other) const;
2222

23+
bool is_normal() const { return type_ == NameType::NORMAL; }
24+
bool is_wildcard() const { return type_ == NameType::WILDCARD; }
25+
bool is_tagged() const { return type_ == NameType::TAGGED; }
26+
2327
private:
2428
Dimname(Symbol name)
2529
: untagged_name_(name), full_name_(name), type_(NameType::NORMAL) {}
@@ -46,7 +50,7 @@ bool CAFFE2_API is_valid_identifier(const std::string& name);
4650
CAFFE2_API c10::optional<Dimname> unify(Dimname dimname, Dimname other);
4751
CAFFE2_API bool match(Dimname dimname, Dimname other);
4852

49-
std::ostream& operator<<(std::ostream& out, const Dimname& dimname);
53+
CAFFE2_API std::ostream& operator<<(std::ostream& out, const Dimname& dimname);
5054

5155
} // namespace at
5256
#endif

aten/src/ATen/NamedTensor.cpp

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,81 @@ bool NamedTensorMeta::has_names() const {
1212
});
1313
}
1414

15+
namespace impl {
16+
17+
// Two Dimnames cannot be in the same Tensor if one of them can refer to the other.
18+
// In practice, this constraint means that a Tensor cannot have duplicate names
19+
// unless they are tagged and the tags are different.
20+
static DimnameList::const_iterator find_incompatible_name(
21+
DimnameList::const_iterator begin,
22+
DimnameList::const_iterator end,
23+
const Dimname& target) {
24+
return std::find_if(begin, end,
25+
[&target](const Dimname& candidate) {
26+
return target.can_refer_to(candidate) || candidate.can_refer_to(target);
27+
});
28+
}
29+
30+
static void check_unique_names(DimnameList names) {
31+
// Strategy: Compare each element with the ones that come after it.
32+
// Although this is O(N^2), in practice N is small (no more than 25).
33+
for (auto it = names.begin(); it != names.end(); ++it) {
34+
auto dup = find_incompatible_name(it + 1, names.end(), *it);
35+
while (dup != names.end()) {
36+
// Simple error message if you're not using tags
37+
TORCH_CHECK(it->type() == NameType::TAGGED || dup->type() == NameType::TAGGED,
38+
"Cannot construct a tensor with duplicate names. Got names: ",
39+
names, ".");
40+
41+
// Complicated error message if you're using tags
42+
TORCH_CHECK(false,
43+
"Cannot construct a tensor with duplicate names unless they are tagged ",
44+
"and have different tags. Got names: ", names, ", offending names: (",
45+
*it, " and ", *dup, ").");
46+
dup = find_incompatible_name(dup + 1, names.end(), *it);
47+
}
48+
}
49+
}
50+
51+
static NamedTensorMeta* get_named_tensor_meta(TensorImpl* impl) {
52+
return static_cast<NamedTensorMeta*>(impl->named_tensor_meta());
53+
}
54+
55+
void internal_set_names_inplace(TensorImpl* impl, optional<DimnameList> names) {
56+
if (!names) {
57+
impl->set_named_tensor_meta(nullptr);
58+
return;
59+
}
60+
auto ndim = impl->dim();
61+
TORCH_CHECK(ndim == names->size(),
62+
"Number of names (", names->size(), ") and "
63+
"number of dimensions in tensor (", ndim, ") ",
64+
"do not match.");
65+
check_unique_names(*names);
66+
67+
auto* meta = get_named_tensor_meta(impl);
68+
if (meta == nullptr) {
69+
impl->set_named_tensor_meta(torch::make_unique<NamedTensorMeta>(*names));
70+
} else {
71+
meta->set_names_(*names);
72+
}
73+
}
74+
75+
optional<DimnameList> internal_get_names(TensorImpl* impl) {
76+
const auto* meta = get_named_tensor_meta(impl);
77+
if (meta == nullptr) {
78+
return nullopt;
79+
} else {
80+
return meta->names();
81+
}
82+
}
83+
84+
bool internal_is_named(TensorImpl* impl) {
85+
const auto* named_tensor_meta = get_named_tensor_meta(impl);
86+
return named_tensor_meta != nullptr && named_tensor_meta->has_names();
87+
}
88+
89+
} // namespace impl
90+
1591
} // namespace at
1692
#endif

aten/src/ATen/NamedTensor.h

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,16 @@
77

88
namespace at {
99

10-
// TensorImpl has a unique_ptr<NamedTensorMetaInterface> field. Ideally we would
11-
// just put optional<vector<Dimname>> into TensorImpl, but the problem with that is
12-
// that c10::Symbol isn't actually a part of the c10 lib (where TensorImpl is).
13-
// In the long term, we should decouple c10::Symbol from aten and toss it into c10.
10+
// XXX: This file exists because TensorImpl is in c10, but Dimname is in ATen.
11+
// Due to the c10/ATen library split, TensorImpl cannot depend on Dimname,
12+
// so we have a couple of workarounds.
13+
//
14+
// In the long term, we'll move Dimname to c10 and everything in this file
15+
// can be refactored out. The main blocker for that is that "c10::Symbol"
16+
// actually exists outside of c10 and needs to be moved in.
17+
18+
// TensorImpl has a unique_ptr<NamedTensorMetaInterface> field.
19+
// XXX: Ideally we would just put optional<vector<Dimname>> into TensorImpl.
1420
struct CAFFE2_API NamedTensorMeta : public c10::NamedTensorMetaInterface {
1521
explicit NamedTensorMeta(int64_t num_names)
1622
: names_(std::vector<Dimname>(num_names, Dimname::wildcard())) {}
@@ -34,5 +40,16 @@ struct CAFFE2_API NamedTensorMeta : public c10::NamedTensorMetaInterface {
3440
std::vector<Dimname> names_;
3541
};
3642

43+
namespace impl {
44+
45+
// Some helper functions on TensorImpl. Useful for working with names in TH.
46+
// XXX: Ideally these would exist as methods on TensorImpl
47+
CAFFE2_API void internal_set_names_inplace(TensorImpl* impl, optional<DimnameList> names);
48+
CAFFE2_API optional<DimnameList> internal_get_names(TensorImpl* impl);
49+
CAFFE2_API bool internal_is_named(TensorImpl* impl);
50+
51+
52+
} // namespace impl
53+
3754
} // namespace at
3855
#endif

aten/src/ATen/NamedTensorUtils.cpp

Lines changed: 94 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -5,60 +5,8 @@
55

66
namespace at {
77

8-
// Two Dimnames cannot be in the same Tensor if one of them can refer to the other.
9-
// In practice, this constraint means that a Tensor cannot have duplicate names
10-
// unless they are tagged and the tags are different.
11-
static DimnameList::const_iterator find_incompatible_name(
12-
DimnameList::const_iterator begin,
13-
DimnameList::const_iterator end,
14-
const Dimname& target) {
15-
return std::find_if(begin, end,
16-
[&target](const Dimname& candidate) {
17-
return target.can_refer_to(candidate) || candidate.can_refer_to(target);
18-
});
19-
}
20-
21-
static void check_unique_names(DimnameList names) {
22-
// Strategy: Compare each element with the ones that come after it.
23-
// Although this is O(N^2), in practice N is small (no more than 25).
24-
for (auto it = names.begin(); it != names.end(); ++it) {
25-
auto dup = find_incompatible_name(it + 1, names.end(), *it);
26-
while (dup != names.end()) {
27-
// Simple error message if you're not using tags
28-
TORCH_CHECK(it->type() == NameType::TAGGED || dup->type() == NameType::TAGGED,
29-
"Cannot construct a tensor with duplicate names. Got names: ",
30-
names, ".");
31-
32-
// Complicated error message if you're using tags
33-
TORCH_CHECK(false,
34-
"Cannot construct a tensor with duplicate names unless they are tagged ",
35-
"and have different tags. Got names: ", names, ", offending names: (",
36-
*it, " and ", *dup, ").");
37-
dup = find_incompatible_name(dup + 1, names.end(), *it);
38-
}
39-
}
40-
}
41-
428
void internal_set_names_inplace(Tensor& tensor, optional<DimnameList> names) {
43-
if (!names) {
44-
tensor.unsafeGetTensorImpl()->set_named_tensor_meta(nullptr);
45-
return;
46-
}
47-
48-
auto ndim = tensor.dim();
49-
TORCH_CHECK(ndim == names->size(),
50-
"Number of names (", names->size(), ") and "
51-
"number of dimensions in tensor (", ndim, ") ",
52-
"do not match.");
53-
check_unique_names(*names);
54-
55-
auto* meta = tensor.get_named_tensor_meta();
56-
if (meta == nullptr) {
57-
tensor.unsafeGetTensorImpl()->set_named_tensor_meta(
58-
torch::make_unique<NamedTensorMeta>(*names));
59-
} else {
60-
meta->set_names_(*names);
61-
}
9+
impl::internal_set_names_inplace(tensor.unsafeGetTensorImpl(), names);
6210
}
6311

6412
// Returns "Tensor['N', 'C', 'H', 'W']" for a tensor with names ('N', 'C', 'H', 'W').
@@ -103,6 +51,95 @@ int64_t dimname_to_position(const Tensor& tensor, Dimname dim) {
10351
return std::distance(names.begin(), it);
10452
}
10553

54+
static void report_positional_error(
55+
const Dimname& name,
56+
const Dimname& other_name,
57+
DimnameList names,
58+
DimnameList other_names) {
59+
// TODO(zou3519): Can improve message by checking if names are alignable and suggesting workarounds
60+
TORCH_CHECK(false,
61+
"Names ", name, " and ", other_name, " do not match positionally ",
62+
"from the right in names ", names, " and ", other_names, ".");
63+
}
64+
65+
static void check_for_misalignment(
66+
const Dimname& name,
67+
DimnameList names,
68+
DimnameList other_names) {
69+
if (name.is_wildcard()) {
70+
return;
71+
}
72+
auto it = std::find_if(other_names.begin(), other_names.end(),
73+
[&](const Dimname& candidate) { return name.can_refer_to(candidate); });
74+
// TODO(zou3519): Can improve message by checking if names are alignable and suggesting workarounds
75+
TORCH_CHECK(it == other_names.end(),
76+
"Names ", names, " and ", other_names, " are misaligned: name ", name,
77+
" appears in a different position from the right.");
78+
}
79+
80+
// Assumption: A DimnameList can have no duplicate full names with
81+
// the exception of wildcards
82+
static std::vector<Dimname> unify_from_right(DimnameList names, DimnameList other_names) {
83+
const auto wildcard = Dimname::wildcard();
84+
const auto size = std::max(names.size(), other_names.size());
85+
auto result = std::vector<Dimname>(size, wildcard);
86+
87+
auto names_it = names.rbegin();
88+
auto other_it = other_names.rbegin();
89+
auto result_it = result.rbegin();
90+
while (names_it != names.rend() || other_it != other_names.rend()) {
91+
// TODO(zou3519): Don't support tagged names for now. They're a little weird.
92+
if (names_it->is_tagged() || other_it->is_tagged()) {
93+
TORCH_INTERNAL_ASSERT("unify_from_right: NYI: tagged names.");
94+
}
95+
96+
const auto& name = names_it == names.rend() ? wildcard : *names_it;
97+
const auto& other_name = other_it == other_names.rend() ? wildcard : *other_it;
98+
99+
// Step 1: Check that the names match
100+
const auto maybeName = unify(name, other_name);
101+
if (!maybeName) {
102+
report_positional_error(name, other_name, names, other_names);
103+
}
104+
*result_it = *maybeName;
105+
106+
// Step 2: Check that the names are not misaligned
107+
if (!names_it->is_normal() || !other_it->is_normal()) {
108+
// Let: N = max(len(names), len(other_names))
109+
// K = # of special names among names and other_names.
110+
// This search (including the outer loop) is O(N*K) but typically # of dims is small.
111+
check_for_misalignment(name, names, other_names);
112+
check_for_misalignment(other_name, other_names, names);
113+
}
114+
115+
if (names_it != names.rend()) {
116+
++names_it;
117+
}
118+
if (other_it != other_names.rend()) {
119+
++other_it;
120+
}
121+
++result_it;
122+
}
123+
return result;
124+
}
125+
126+
// Assumption: A DimnameList can have no duplicate full names with
127+
// the exception of wildcards
128+
CAFFE2_API optional<std::vector<Dimname>>
129+
unify_from_right(optional<DimnameList> names, optional<DimnameList> other_names) {
130+
if (!names && !other_names) {
131+
return nullopt;
132+
}
133+
if (!names) {
134+
return other_names.value().vec();
135+
}
136+
if (!other_names) {
137+
return names.value().vec();
138+
}
139+
return unify_from_right(*names, *other_names);
140+
}
141+
142+
106143
namespace namedinference {
107144

108145
optional<std::vector<Dimname>> erase_name(optional<DimnameList> self_names, int64_t dim) {
@@ -114,6 +151,10 @@ optional<std::vector<Dimname>> erase_name(optional<DimnameList> self_names, int6
114151
return outnames;
115152
}
116153

154+
void propagate_names(Tensor& result, const Tensor& src) {
155+
at::internal_set_names_inplace(result, src.names());
156+
}
157+
117158
} // namespace namedinference
118159
} // namespace at
119160
#endif

0 commit comments

Comments
 (0)