mirror of
https://github.com/saymrwulf/pytorch.git
synced 2026-05-15 21:00:47 +00:00
Summary: Pull Request resolved: https://github.com/pytorch/pytorch/pull/36222 Reland of #35706, with fixes to code analyzer. It is extremely common to define implementations of operators at a specific dispatch key, so we add an overload to impl specifically for this case. I then delete most uses of torch::dispatch dispatch_autograd call sites can't make use of this overload. So instead the new preferred way to specify something as autograd is to pass kAutograd as the dispatch key (short form, analogous to kCPU/kCUDA which we support today). I flip flopped about whether or not kAutograd should have the type DispatchKey or some other type (to help better encapsulate the DispatchKey enum); this is more direct and I can't think of any BC problems from this usage. Some other reorganization I did: - I renamed all of the worker functions in op_registration to have a leading underscore and made them private, just to make it more clear what the public versus private API were (the private API shouldn't be used by users because it doesn't come with && overloads) Note that this means I needed to adjust the regex in the code analyzer, because - In a few places where I was touching lines already, I replaced full DispatchKey typed out enums with shorter kFoo names, similar to kAutograd but I didn't publish these globally. - Code analyzer now prints a unified diff, and in the other order (because I tend to think of the diff as reporting how the /new/ result is different) Signed-off-by: Edward Z. Yang <ezyang@fb.com> Test Plan: Imported from OSS Differential Revision: D20929256 Pulled By: ezyang fbshipit-source-id: c69b803d2b3a1a8aff70e14da33d3adec5239f13
159 lines
4.5 KiB
Bash
Executable file
159 lines
4.5 KiB
Bash
Executable file
#!/bin/bash
|
|
##############################################################################
|
|
# Build LLVM code analyzer and analyze torch code dependency.
|
|
##############################################################################
|
|
#
|
|
# Example usage:
|
|
#
|
|
# 1. Analyze torch and generate yaml file of op dependency transitive closure:
|
|
# LLVM_DIR=${HOME}/src/llvm8/build/install \
|
|
# ANALYZE_TORCH=1 tools/code_analyzer/build.sh
|
|
#
|
|
# 2. Analyze test project and compare with expected result:
|
|
# LLVM_DIR=${HOME}/src/llvm8/build/install \
|
|
# ANALYZE_TEST=1 CHECK_RESULT=1 tools/code_analyzer/build.sh
|
|
#
|
|
# 3. Analyze torch and generate yaml file of op dependency with debug path:
|
|
# LLVM_DIR=${HOME}/src/llvm8/build/install \
|
|
# ANALYZE_TORCH=1 tools/code_analyzer/build.sh -debug_path=true
|
|
#
|
|
# If you're a Facebook employee, chances are you're running on CentOS 8.
|
|
# If that's the case, you can install all the dependencies you need with:
|
|
#
|
|
# sudo dnf install llvm-devel llvm-static clang ncurses-devel
|
|
#
|
|
# and then set LLVM_DIR=/usr
|
|
|
|
set -ex
|
|
|
|
SRC_ROOT="$( cd "$(dirname "$0")"/../.. ; pwd -P)"
|
|
ANALYZER_SRC_HOME="${SRC_ROOT}/tools/code_analyzer"
|
|
|
|
# Clang/LLVM path
|
|
export LLVM_DIR="${LLVM_DIR:-/usr/lib/llvm-8}"
|
|
export CC="${LLVM_DIR}/bin/clang"
|
|
export CXX="${LLVM_DIR}/bin/clang++"
|
|
EXTRA_ANALYZER_FLAGS=$@
|
|
|
|
BUILD_ROOT="${BUILD_ROOT:-${SRC_ROOT}/build_code_analyzer}"
|
|
WORK_DIR="${BUILD_ROOT}/work"
|
|
|
|
mkdir -p "${BUILD_ROOT}"
|
|
mkdir -p "${WORK_DIR}"
|
|
cd "${BUILD_ROOT}"
|
|
|
|
build_analyzer() {
|
|
cmake "${ANALYZER_SRC_HOME}" -DCMAKE_BUILD_TYPE=Release
|
|
|
|
if [ -z "${MAX_JOBS}" ]; then
|
|
if [ "$(uname)" == 'Darwin' ]; then
|
|
MAX_JOBS=$(sysctl -n hw.ncpu)
|
|
else
|
|
MAX_JOBS=$(nproc)
|
|
fi
|
|
fi
|
|
|
|
make "-j${MAX_JOBS}"
|
|
}
|
|
|
|
build_torch_mobile() {
|
|
TORCH_BUILD_ROOT="${BUILD_ROOT}/build_mobile"
|
|
TORCH_INSTALL_PREFIX="${TORCH_BUILD_ROOT}/install"
|
|
|
|
if [ ! -d "${TORCH_INSTALL_PREFIX}" ]; then
|
|
BUILD_ROOT="${TORCH_BUILD_ROOT}" "${SRC_ROOT}/scripts/build_mobile.sh" \
|
|
-DCMAKE_CXX_FLAGS="-S -emit-llvm -DSTRIP_ERROR_MESSAGES" \
|
|
-DUSE_STATIC_DISPATCH=OFF
|
|
fi
|
|
}
|
|
|
|
build_test_project() {
|
|
TEST_SRC_ROOT="${SRC_ROOT}/test/mobile/op_deps"
|
|
TEST_BUILD_ROOT="${BUILD_ROOT}/build_test"
|
|
TEST_INSTALL_PREFIX="${TEST_BUILD_ROOT}/install"
|
|
|
|
BUILD_ROOT="${TEST_BUILD_ROOT}" \
|
|
TORCH_INSTALL_PREFIX="${TORCH_INSTALL_PREFIX}" \
|
|
"${TEST_SRC_ROOT}/build.sh" \
|
|
-DCMAKE_CXX_FLAGS="-S -emit-llvm -DSTRIP_ERROR_MESSAGES"
|
|
}
|
|
|
|
call_analyzer() {
|
|
ANALYZER_BIN="${BUILD_ROOT}/analyzer" \
|
|
INPUT="${INPUT}" OUTPUT="${OUTPUT}" FORMAT="${FORMAT}" \
|
|
EXTRA_ANALYZER_FLAGS="${EXTRA_ANALYZER_FLAGS}" \
|
|
"${ANALYZER_SRC_HOME}/run_analyzer.sh"
|
|
}
|
|
|
|
analyze_torch_mobile() {
|
|
INPUT="${WORK_DIR}/torch.ll"
|
|
FORMAT="${FORMAT:=yaml}"
|
|
OUTPUT="${WORK_DIR}/torch_result.${FORMAT}"
|
|
|
|
if [ ! -f "${INPUT}" ]; then
|
|
# Link libtorch into a single module
|
|
# TODO: invoke llvm-link from cmake directly to avoid this hack.
|
|
# TODO: include *.c.o when there is meaningful fan-out from pure-c code.
|
|
"${LLVM_DIR}/bin/llvm-link" -S \
|
|
$(find "${TORCH_BUILD_ROOT}" -name '*.cpp.o' -o -name '*.cc.o') \
|
|
-o "${INPUT}"
|
|
fi
|
|
|
|
# Analyze dependency
|
|
call_analyzer
|
|
|
|
if [ -n "${DEPLOY}" ]; then
|
|
DEST="${BUILD_ROOT}/pt_deps.bzl"
|
|
cat > ${DEST} <<- EOM
|
|
# Generated for selective build without using static dispatch.
|
|
# Manually run the script to update:
|
|
# ANALYZE_TORCH=1 FORMAT=py DEPLOY=1 tools/code_analyzer/build.sh
|
|
EOM
|
|
printf "TORCH_DEPS = " >> ${DEST}
|
|
cat "${OUTPUT}" >> ${DEST}
|
|
echo "Deployed file at: ${DEST}"
|
|
fi
|
|
}
|
|
|
|
analyze_test_project() {
|
|
INPUT="${WORK_DIR}/test.ll"
|
|
FORMAT="${FORMAT:=yaml}"
|
|
OUTPUT="${WORK_DIR}/test_result.${FORMAT}"
|
|
|
|
# Link into a single module (only need c10 and OpLib srcs)
|
|
# TODO: invoke llvm-link from cmake directly to avoid this hack.
|
|
"${LLVM_DIR}/bin/llvm-link" -S \
|
|
$(find "${TORCH_BUILD_ROOT}" -path '*/c10*' \( -name '*.cpp.o' -o -name '*.cc.o' \)) \
|
|
$(find "${TEST_BUILD_ROOT}" -path '*/OpLib*' \( -name '*.cpp.o' -o -name '*.cc.o' \)) \
|
|
-o "${INPUT}"
|
|
|
|
# Analyze dependency
|
|
call_analyzer
|
|
|
|
if [ -n "${CHECK_RESULT}" ]; then
|
|
check_test_result
|
|
fi
|
|
}
|
|
|
|
check_test_result() {
|
|
if cmp -s "${OUTPUT}" "${TEST_SRC_ROOT}/expected_deps.yaml"; then
|
|
echo "Test result is the same as expected."
|
|
else
|
|
echo "Test result is DIFFERENT from expected!"
|
|
diff -u "${TEST_SRC_ROOT}/expected_deps.yaml" "${OUTPUT}"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
build_analyzer
|
|
|
|
if [ -n "${ANALYZE_TORCH}" ]; then
|
|
build_torch_mobile
|
|
analyze_torch_mobile
|
|
fi
|
|
|
|
if [ -n "${ANALYZE_TEST}" ]; then
|
|
build_torch_mobile
|
|
build_test_project
|
|
analyze_test_project
|
|
fi
|