clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name init.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -analyzer-output=html -analyzer-checker=python -analyzer-disable-checker=deadcode -analyzer-config prune-paths=true,suppress-c++-stdlib=true,suppress-inlined-defensive-checks=false,suppress-null-return-paths=false,crosscheck-with-z3=true,model-path=/opt/pyrefcon/lib/pyrefcon/models/models -analyzer-config experimental-enable-naive-ctu-analysis=true,ctu-dir=/tmp/pyrefcon/pytorch/csa-scan,ctu-index-name=/tmp/pyrefcon/pytorch/csa-scan/externalDefMap.txt,ctu-invocation-list=/tmp/pyrefcon/pytorch/csa-scan/invocations.yaml,display-ctu-progress=false -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -relaxed-aliasing -fno-rounding-math -ffp-exception-behavior=ignore -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/tmp/pyrefcon/pytorch/build -resource-dir /opt/pyrefcon/lib/clang/13.0.0 -isystem third_party/gloo -isystem ../cmake/../third_party/gloo -isystem ../cmake/../third_party/googletest/googlemock/include -isystem ../cmake/../third_party/googletest/googletest/include -isystem ../third_party/protobuf/src -isystem ../third_party/gemmlowp -isystem ../third_party/neon2sse -isystem ../third_party/XNNPACK/include -isystem ../third_party -isystem ../cmake/../third_party/eigen -isystem /opt/pyrefcon/lib/pyrefcon/models/python3.8 -isystem /usr/lib/python3/dist-packages/numpy/core/include -isystem ../cmake/../third_party/pybind11/include -isystem /usr/lib/x86_64-linux-gnu/openmpi/include/openmpi -isystem /usr/lib/x86_64-linux-gnu/openmpi/include -isystem ../third_party/ideep/mkl-dnn/include -isystem ../third_party/ideep/include -D BUILDING_TESTS -D FMT_HEADER_ONLY=1 -D HAVE_MALLOC_USABLE_SIZE=1 -D HAVE_MMAP=1 -D HAVE_SHM_OPEN=1 -D HAVE_SHM_UNLINK=1 -D MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS -D ONNXIFI_ENABLE_EXT=1 -D ONNX_ML=1 -D ONNX_NAMESPACE=onnx_torch -D THP_BUILD_MAIN_LIB -D USE_C10D -D USE_C10D_GLOO -D USE_C10D_MPI -D USE_DISTRIBUTED -D USE_EXTERNAL_MZCRC -D USE_NUMPY -D USE_RPC -D USE_TENSORPIPE -D USE_VALGRIND -D _FILE_OFFSET_BITS=64 -D torch_python_EXPORTS -I aten/src -I ../aten/src -I . -I ../ -I ../cmake/../third_party/benchmark/include -I caffe2/contrib/aten -I ../third_party/onnx -I third_party/onnx -I ../third_party/foxi -I third_party/foxi -I ../torch/.. -I ../torch/../aten/src -I ../torch/../aten/src/TH -I caffe2/aten/src -I third_party -I ../torch/../third_party/valgrind-headers -I ../torch/../third_party/gloo -I ../torch/../third_party/onnx -I ../torch/csrc -I ../torch/csrc/api/include -I ../torch/lib -I ../torch/lib/libshm -I ../torch/csrc/distributed -I ../torch/csrc/api -I ../c10/.. -I third_party/ideep/mkl-dnn/include -I ../third_party/ideep/mkl-dnn/src/../include -I ../torch/lib/libshm/../../../torch/lib -I ../third_party/fmt/include -D USE_PTHREADPOOL -D NDEBUG -D USE_KINETO -D LIBKINETO_NOCUPTI -D USE_FBGEMM -D USE_QNNPACK -D USE_PYTORCH_QNNPACK -D USE_XNNPACK -D SYMBOLICATE_MOBILE_DEBUG_HANDLE -D HAVE_AVX_CPU_DEFINITION -D HAVE_AVX2_CPU_DEFINITION -D NDEBUG -D NDEBUG -D CAFFE2_USE_GLOO -D HAVE_GCC_GET_CPUID -D USE_AVX -D USE_AVX2 -D TH_HAVE_THREAD -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/x86_64-linux-gnu/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/backward -internal-isystem /opt/pyrefcon/lib/clang/13.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -Wno-narrowing -Wall -Wextra -Werror=return-type -Wno-missing-field-initializers -Wno-type-limits -Wno-array-bounds -Wno-unknown-pragmas -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wno-unused-function -Wno-unused-result -Wno-unused-local-typedefs -Wno-strict-overflow -Wno-strict-aliasing -Wno-error=deprecated-declarations -Wno-stringop-overflow -Wno-psabi -Wno-error=pedantic -Wno-error=redundant-decls -Wno-error=old-style-cast -Wno-unused-but-set-variable -Wno-maybe-uninitialized -Werror=format -Werror=cast-function-type -Wno-stringop-overflow -Wno-write-strings -Wno-strict-aliasing -Wno-cast-function-type -w -std=gnu++14 -fdeprecated-macro -fdebug-compilation-dir=/tmp/pyrefcon/pytorch/build -ferror-limit 19 -fvisibility-inlines-hidden -fopenmp -fopenmp-cuda-parallel-target-regions -pthread -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -faligned-allocation -fcolor-diagnostics -vectorize-loops -vectorize-slp -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/pyrefcon/pytorch/csa-scan/reports -x c++ ../torch/csrc/distributed/autograd/init.cpp
| 1 | #include <torch/csrc/autograd/python_cpp_function.h> |
| 2 | #include <torch/csrc/distributed/autograd/autograd.h> |
| 3 | #include <torch/csrc/jit/python/pybind_utils.h> |
| 4 | #include <torch/csrc/python_headers.h> |
| 5 | #include <torch/csrc/utils/object_ptr.h> |
| 6 | #include <torch/csrc/utils/pybind.h> |
| 7 | #include <torch/types.h> |
| 8 | |
| 9 | namespace torch { |
| 10 | namespace distributed { |
| 11 | namespace autograd { |
| 12 | |
| 13 | namespace { |
| 14 | |
| 15 | template <typename T> |
| 16 | using shared_ptr_class_ = py::class_<T, std::shared_ptr<T>>; |
| 17 | |
| 18 | PyObject* dist_autograd_init(PyObject* _unused, PyObject* noargs) { |
| 19 | auto autograd_module = |
| 20 | THPObjectPtr(PyImport_ImportModule("torch.distributed.autograd")); |
| 1 | Calling 'PyImport_ImportModule' | |
|
| 3 | | Returning from 'PyImport_ImportModule' | |
|
| 8 | | PyObject ownership leak with reference count of 1 |
|
| 21 | if (!autograd_module) { |
| 4 | | Assuming the condition is false | |
|
| |
| 22 | throw python_error(); |
| 23 | } |
| 24 | |
| 25 | auto torch_C_module = THPObjectPtr(PyImport_ImportModule("torch._C")); |
| 26 | if (!torch_C_module) { |
| 6 | | Assuming the condition is true | |
|
| |
| 27 | throw python_error(); |
| 28 | } |
| 29 | |
| 30 | auto torch_C_m = py::handle(torch_C_module).cast<py::module>(); |
| 31 | auto m = torch_C_m.def_submodule("_distributed_autograd", "distributed autograd bindings"); |
| 32 | |
| 33 | auto module = py::handle(m).cast<py::module>(); |
| 34 | |
| 35 | auto distAutogradContext = |
| 36 | shared_ptr_class_<DistAutogradContext>(module, "DistAutogradContext") |
| 37 | .def( |
| 38 | "_context_id", |
| 39 | &DistAutogradContext::contextId, |
| 40 | py::call_guard<py::gil_scoped_release>()) |
| 41 | .def( |
| 42 | "_recv_functions", |
| 43 | [](const DistAutogradContext& ctx) { |
| 44 | std::map<int64_t, py::object> funcs; |
| 45 | for (const auto& map_entry : ctx.recvFunctions()) { |
| 46 | funcs.emplace( |
| 47 | map_entry.first, |
| 48 | py::reinterpret_steal<py::object>( |
| 49 | torch::autograd::functionToPyObject( |
| 50 | map_entry.second))); |
| 51 | } |
| 52 | return funcs; |
| 53 | }) |
| 54 | .def( |
| 55 | "_send_functions", |
| 56 | [](const ContextPtr& ctx) { |
| 57 | std::map<int64_t, py::object> funcs; |
| 58 | for (const auto& map_entry : ctx->sendFunctions()) { |
| 59 | funcs.emplace( |
| 60 | map_entry.first, |
| 61 | py::reinterpret_steal<py::object>( |
| 62 | torch::autograd::functionToPyObject( |
| 63 | map_entry.second))); |
| 64 | } |
| 65 | return funcs; |
| 66 | }) |
| 67 | .def("_known_worker_ids", &DistAutogradContext::getKnownWorkerIds); |
| 68 | |
| 69 | module.def( |
| 70 | "_new_context", |
| 71 | []() -> const ContextPtr { |
| 72 | return DistAutogradContainer::getInstance().newContext(); |
| 73 | }, |
| 74 | py::return_value_policy::reference); |
| 75 | |
| 76 | module.def( |
| 77 | "_release_context", |
| 78 | [](int64_t context_id) { |
| 79 | return DistAutogradContainer::getInstance().releaseContext(context_id); |
| 80 | }, |
| 81 | py::call_guard<py::gil_scoped_release>()); |
| 82 | |
| 83 | module.def("_get_max_id", []() { |
| 84 | return DistAutogradContainer::getInstance().getMaxId(); |
| 85 | }); |
| 86 | |
| 87 | module.def( |
| 88 | "_is_valid_context", |
| 89 | [](int64_t worker_id) { |
| 90 | DistAutogradContainer::getInstance().isValidContext(worker_id); |
| 91 | }, |
| 92 | py::call_guard<py::gil_scoped_release>()); |
| 93 | |
| 94 | module.def( |
| 95 | "_retrieve_context", |
| 96 | [](int64_t context_id) -> const ContextPtr { |
| 97 | return DistAutogradContainer::getInstance().retrieveContext(context_id); |
| 98 | }, |
| 99 | py::return_value_policy::reference); |
| 100 | |
| 101 | module.def( |
| 102 | "_current_context", |
| 103 | []() -> const ContextPtr { |
| 104 | return DistAutogradContainer::getInstance().currentContext(); |
| 105 | }, |
| 106 | py::return_value_policy::reference); |
| 107 | |
| 108 | module.def( |
| 109 | "_init", |
| 110 | [](int64_t worker_id) { DistAutogradContainer::init(worker_id); }, |
| 111 | py::call_guard<py::gil_scoped_release>()); |
| 112 | |
| 113 | module.def( |
| 114 | "_get_debug_info", |
| 115 | []() { return DistEngine::getInstance().getDebugInfo(); }, |
| 116 | py::call_guard<py::gil_scoped_release>()); |
| 117 | |
| 118 | py::options options; |
| 119 | options.disable_function_signatures(); |
| 120 | |
| 121 | module.def( |
| 122 | "backward", |
| 123 | backward, |
| 124 | R"( |
| 125 | backward(context_id: int, roots: List[Tensor], retain_graph = False) -> None |
| 126 | |
| 127 | Kicks off the distributed backward pass using the provided roots. This |
| 128 | currently implements the :ref:`fast-mode-algorithm` which |
| 129 | assumes all RPC messages sent in the same distributed autograd context |
| 130 | across workers would be part of the autograd graph during the backward pass. |
| 131 | |
| 132 | We use the provided roots to discover the autograd graph and compute |
| 133 | appropriate dependencies. This method blocks until the entire |
| 134 | autograd computation is done. |
| 135 | |
| 136 | We accumulate the gradients in the appropriate |
| 137 | :class:`torch.distributed.autograd.context` on each of the nodes. The autograd |
| 138 | context to be used is looked up given the ``context_id`` that is passed in when |
| 139 | :meth:`torch.distributed.autograd.backward` is called. If there is no valid |
| 140 | autograd context corresponding to the given ID, we throw an error. You can |
| 141 | retrieve the accumulated gradients using the |
| 142 | :meth:`~torch.distributed.autograd.get_gradients` API. |
| 143 | |
| 144 | Arguments: |
| 145 | context_id (int): The autograd context id for which we should retrieve the gradients. |
| 146 | roots (list): Tensors which represent the roots of the autograd |
| 147 | computation. All the tensors should be scalars. |
| 148 | retain_graph(bool, optional): If False, the graph used to compute the grad |
| 149 | will be freed. Note that in nearly all cases setting this |
| 150 | option to True is not needed and often can be worked around |
| 151 | in a much more efficient way. Usually, you need to set this |
| 152 | to True to run backward multiple times. |
| 153 | |
| 154 | Example:: |
| 155 | >>> import torch.distributed.autograd as dist_autograd |
| 156 | >>> with dist_autograd.context() as context_id: |
| 157 | >>> pred = model.forward() |
| 158 | >>> loss = loss_func(pred, loss) |
| 159 | >>> dist_autograd.backward(context_id, loss) |
| 160 | )", |
| 161 | py::arg("contextId"), |
| 162 | py::arg("roots"), |
| 163 | py::arg("retain_graph") = false, |
| 164 | py::call_guard<py::gil_scoped_release>()); |
| 165 | |
| 166 | module.def( |
| 167 | "get_gradients", |
| 168 | [](int64_t contextId) -> py::dict { |
| 169 | const auto& autogradContext = |
| 170 | DistAutogradContainer::getInstance().retrieveContext(contextId); |
| 171 | return torch::jit::toPyObject(IValue(autogradContext->getGradients())); |
| 172 | }, |
| 173 | R"( |
| 174 | get_gradients(context_id: int) -> Dict[Tensor, Tensor] |
| 175 | |
| 176 | Retrieves a map from Tensor to the appropriate gradient for that Tensor |
| 177 | accumulated in the provided context corresponding to the given ``context_id`` |
| 178 | as part of the distributed autograd backward pass. |
| 179 | |
| 180 | Arguments: |
| 181 | context_id(int): The autograd context id for which we should retrieve the |
| 182 | gradients. |
| 183 | |
| 184 | Returns: |
| 185 | A map where the key is the Tensor and the value is the associated gradient |
| 186 | for that Tensor. |
| 187 | |
| 188 | Example:: |
| 189 | >>> import torch.distributed.autograd as dist_autograd |
| 190 | >>> with dist_autograd.context() as context_id: |
| 191 | >>> t1 = torch.rand((3, 3), requires_grad=True) |
| 192 | >>> t2 = torch.rand((3, 3), requires_grad=True) |
| 193 | >>> loss = t1 + t2 |
| 194 | >>> dist_autograd.backward(context_id, [loss.sum()]) |
| 195 | >>> grads = dist_autograd.get_gradients(context_id) |
| 196 | >>> print(grads[t1]) |
| 197 | >>> print(grads[t2]) |
| 198 | )", |
| 199 | py::arg("context_id")); |
| 200 | |
| 201 | Py_RETURN_TRUE; |
| 202 | } |
| 203 | } |
| 204 | |
| 205 | static PyMethodDef methods[] = { |
| 206 | {"_dist_autograd_init", |
| 207 | dist_autograd_init, |
| 208 | METH_NOARGS, |
| 209 | nullptr}, |
| 210 | {nullptr, nullptr, 0, nullptr}}; |
| 211 | |
| 212 | PyMethodDef* python_functions() { |
| 213 | return methods; |
| 214 | } |
| 215 | |
| 216 | } |
| 217 | } |
| 218 | } |