Browse Source
Feat: Achieved perfect Conv1, good BN1/ReLU1/MaxPool similarity. README updated.
resnet
Feat: Achieved perfect Conv1, good BN1/ReLU1/MaxPool similarity. README updated.
resnet
715 changed files with 30161 additions and 57635 deletions
-
100CMakeLists.txt
-
17README.md
-
BINbin/tracking_demo
-
154build.sh
-
212build/CMakeCache.txt
-
22build/CMakeFiles/3.22.1/CMakeCUDACompiler.cmake
-
BINbuild/CMakeFiles/3.22.1/CMakeDetermineCompilerABI_CUDA.bin
-
2build/CMakeFiles/3.22.1/CMakeSystem.cmake
-
BINbuild/CMakeFiles/3.22.1/CompilerIdCUDA/a.out
-
4246build/CMakeFiles/3.22.1/CompilerIdCUDA/tmp/CMakeCUDACompilerId.cpp1.ii
-
4120build/CMakeFiles/3.22.1/CompilerIdCUDA/tmp/CMakeCUDACompilerId.cpp4.ii
-
6build/CMakeFiles/3.22.1/CompilerIdCUDA/tmp/CMakeCUDACompilerId.cudafe1.c
-
7546build/CMakeFiles/3.22.1/CompilerIdCUDA/tmp/CMakeCUDACompilerId.cudafe1.cpp
-
4build/CMakeFiles/3.22.1/CompilerIdCUDA/tmp/CMakeCUDACompilerId.cudafe1.gpu
-
BINbuild/CMakeFiles/3.22.1/CompilerIdCUDA/tmp/CMakeCUDACompilerId.fatbin
-
38build/CMakeFiles/3.22.1/CompilerIdCUDA/tmp/CMakeCUDACompilerId.fatbin.c
-
BINbuild/CMakeFiles/3.22.1/CompilerIdCUDA/tmp/CMakeCUDACompilerId.o
-
6build/CMakeFiles/3.22.1/CompilerIdCUDA/tmp/CMakeCUDACompilerId.ptx
-
BINbuild/CMakeFiles/3.22.1/CompilerIdCUDA/tmp/CMakeCUDACompilerId.sm_52.cubin
-
BINbuild/CMakeFiles/3.22.1/CompilerIdCUDA/tmp/a_dlink.fatbin
-
57build/CMakeFiles/3.22.1/CompilerIdCUDA/tmp/a_dlink.fatbin.c
-
BINbuild/CMakeFiles/3.22.1/CompilerIdCUDA/tmp/a_dlink.o
-
BINbuild/CMakeFiles/3.22.1/CompilerIdCUDA/tmp/a_dlink.sm_52.cubin
-
1156build/CMakeFiles/CMakeOutput.log
-
44build/CMakeFiles/Makefile.cmake
-
62build/CMakeFiles/Makefile2
-
3build/CMakeFiles/TargetDirectories.txt
-
2build/CMakeFiles/bb_regressor.dir/DependInfo.cmake
-
26build/CMakeFiles/bb_regressor.dir/build.make
-
BINbuild/CMakeFiles/bb_regressor.dir/cimp/bb_regressor/bb_regressor.cpp.o
-
5157build/CMakeFiles/bb_regressor.dir/cimp/bb_regressor/bb_regressor.cpp.o.d
-
6build/CMakeFiles/bb_regressor.dir/cmake_clean.cmake
-
5367build/CMakeFiles/bb_regressor.dir/compiler_depend.internal
-
15247build/CMakeFiles/bb_regressor.dir/compiler_depend.make
-
11build/CMakeFiles/bb_regressor.dir/flags.make
-
2build/CMakeFiles/bb_regressor.dir/link.txt
-
BINbuild/CMakeFiles/classifier.dir/cimp/classifier/classifier.cpp.o
-
5088build/CMakeFiles/classifier.dir/cimp/classifier/classifier.cpp.o.d
-
5123build/CMakeFiles/classifier.dir/compiler_depend.internal
-
14799build/CMakeFiles/classifier.dir/compiler_depend.make
-
4build/CMakeFiles/classifier.dir/flags.make
-
1build/CMakeFiles/tracking_demo.dir/DependInfo.cmake
-
32build/CMakeFiles/tracking_demo.dir/build.make
-
BINbuild/CMakeFiles/tracking_demo.dir/cimp/demo.cpp.o
-
4910build/CMakeFiles/tracking_demo.dir/cimp/demo.cpp.o.d
-
2148build/CMakeFiles/tracking_demo.dir/compiler_depend.make
-
4build/CMakeFiles/tracking_demo.dir/flags.make
-
2build/CMakeFiles/tracking_demo.dir/link.txt
-
111build/Makefile
-
40build/cmake_install.cmake
-
3build/install_manifest.txt
-
BINbuild/libbb_regressor.a
-
BINbuild/libclassifier.a
-
BINbuild/tracking_demo
-
84cimp/bb_regressor/bb_regressor.cpp
-
2cimp/bb_regressor/bb_regressor.h
-
34cimp/bb_regressor/prroi_pooling/prroi_pooling_gpu_impl.cu
-
287cimp/resnet/resnet.cpp
-
82cimp/resnet/resnet.h
-
156cmake-build-debug/CMakeCache.txt
-
13cmake-build-debug/CMakeFiles/clion-Debug-log.txt
-
BINcmake-build-debug/CMakeFiles/clion-environment.txt
-
178export_resnet_individual_tensors.py
-
205export_resnet_raw.py
-
BINexported_weights/backbone_regenerated/bn1_bias.pt
-
BINexported_weights/backbone_regenerated/bn1_num_batches_tracked.pt
-
BINexported_weights/backbone_regenerated/bn1_running_mean.pt
-
BINexported_weights/backbone_regenerated/bn1_running_var.pt
-
BINexported_weights/backbone_regenerated/bn1_weight.pt
-
BINexported_weights/backbone_regenerated/conv1_weight.pt
-
BINexported_weights/backbone_regenerated/fc_bias.pt
-
BINexported_weights/backbone_regenerated/fc_weight.pt
-
BINexported_weights/backbone_regenerated/layer1_0_bn1_bias.pt
-
BINexported_weights/backbone_regenerated/layer1_0_bn1_num_batches_tracked.pt
-
BINexported_weights/backbone_regenerated/layer1_0_bn1_running_mean.pt
-
BINexported_weights/backbone_regenerated/layer1_0_bn1_running_var.pt
-
BINexported_weights/backbone_regenerated/layer1_0_bn1_weight.pt
-
BINexported_weights/backbone_regenerated/layer1_0_bn2_bias.pt
-
BINexported_weights/backbone_regenerated/layer1_0_bn2_num_batches_tracked.pt
-
BINexported_weights/backbone_regenerated/layer1_0_bn2_running_mean.pt
-
BINexported_weights/backbone_regenerated/layer1_0_bn2_running_var.pt
-
BINexported_weights/backbone_regenerated/layer1_0_bn2_weight.pt
-
BINexported_weights/backbone_regenerated/layer1_0_bn3_bias.pt
-
BINexported_weights/backbone_regenerated/layer1_0_bn3_num_batches_tracked.pt
-
BINexported_weights/backbone_regenerated/layer1_0_bn3_running_mean.pt
-
BINexported_weights/backbone_regenerated/layer1_0_bn3_running_var.pt
-
BINexported_weights/backbone_regenerated/layer1_0_bn3_weight.pt
-
BINexported_weights/backbone_regenerated/layer1_0_conv1_weight.pt
-
BINexported_weights/backbone_regenerated/layer1_0_conv2_weight.pt
-
BINexported_weights/backbone_regenerated/layer1_0_conv3_weight.pt
-
BINexported_weights/backbone_regenerated/layer1_0_downsample_0_weight.pt
-
BINexported_weights/backbone_regenerated/layer1_0_downsample_1_bias.pt
-
BINexported_weights/backbone_regenerated/layer1_0_downsample_1_num_batches_tracked.pt
-
BINexported_weights/backbone_regenerated/layer1_0_downsample_1_running_mean.pt
-
BINexported_weights/backbone_regenerated/layer1_0_downsample_1_running_var.pt
-
BINexported_weights/backbone_regenerated/layer1_0_downsample_1_weight.pt
-
BINexported_weights/backbone_regenerated/layer1_1_bn1_bias.pt
-
BINexported_weights/backbone_regenerated/layer1_1_bn1_num_batches_tracked.pt
-
BINexported_weights/backbone_regenerated/layer1_1_bn1_running_mean.pt
-
BINexported_weights/backbone_regenerated/layer1_1_bn1_running_var.pt
@ -1,82 +1,120 @@ |
|||
#!/bin/bash |
|||
|
|||
export PATH=/usr/local/cuda-11.5/bin:$PATH |
|||
export LD_LIBRARY_PATH=/usr/local/cuda-11.5/lib64:$LD_LIBRARY_PATH |
|||
# Target LibTorch 1.8.0+cu111 to match Python environment |
|||
LIBTORCH_VERSION="1.8.0" |
|||
LIBTORCH_CUDA_VERSION_SHORT="cu111" # e.g., cu111, cu117, cu118 |
|||
TARGET_CUDA_VERSION_FOR_LIBTORCH="11.1" # e.g., 11.1, 11.7, 11.8 |
|||
|
|||
# --- CUDA Setup --- |
|||
# Try to find the exact CUDA version LibTorch was built against |
|||
PROPOSED_CUDA_HOME="/usr/local/cuda-${TARGET_CUDA_VERSION_FOR_LIBTORCH}" |
|||
|
|||
if [ -d "${PROPOSED_CUDA_HOME}" ] && [ -x "${PROPOSED_CUDA_HOME}/bin/nvcc" ]; then |
|||
echo "Found targeted CUDA version for LibTorch: ${TARGET_CUDA_VERSION_FOR_LIBTORCH} at ${PROPOSED_CUDA_HOME}" |
|||
export CUDA_HOME="${PROPOSED_CUDA_HOME}" |
|||
else |
|||
echo "Warning: Targeted CUDA version ${TARGET_CUDA_VERSION_FOR_LIBTORCH} for LibTorch not found at ${PROPOSED_CUDA_HOME}." |
|||
# Fallback to user's specified CUDA_HOME or a default, and warn about potential mismatch |
|||
if [ -z "$CUDA_HOME" ]; then # If CUDA_HOME is not already set in the environment |
|||
export CUDA_HOME=/usr/local/cuda-11.8 # Default fallback |
|||
echo "Warning: Using fallback CUDA_HOME: $CUDA_HOME. This might mismatch LibTorch's CUDA version ${TARGET_CUDA_VERSION_FOR_LIBTORCH}." |
|||
else |
|||
echo "Warning: Using externally set CUDA_HOME: $CUDA_HOME. Ensure this is compatible with LibTorch for CUDA ${TARGET_CUDA_VERSION_FOR_LIBTORCH}." |
|||
fi |
|||
# We proceed, but there's a higher chance of issues if nvcc version doesn't align with LibTorch's CUDA build. |
|||
fi |
|||
|
|||
export PATH=${CUDA_HOME}/bin:${PATH} |
|||
export LD_LIBRARY_PATH=${CUDA_HOME}/lib64:${LD_LIBRARY_PATH} |
|||
export CMAKE_CUDA_COMPILER=${CUDA_HOME}/bin/nvcc |
|||
|
|||
# Exit on error |
|||
set -e |
|||
|
|||
# Print info |
|||
# --- vcpkg setup --- |
|||
# Remove explicit VCPKG_INSTALLATION_ROOT. |
|||
# The CMAKE_TOOLCHAIN_FILE will be set in the cmake command if vcpkg is part of the project. |
|||
# It's often good practice to have vcpkg as a submodule or managed by CMake FetchContent. |
|||
|
|||
echo "Building C++ Tracker" |
|||
echo "Using CUDA_HOME: $CUDA_HOME" |
|||
echo "Using PATH: $PATH" |
|||
echo "Using LD_LIBRARY_PATH: $LD_LIBRARY_PATH" |
|||
|
|||
# Set CUDA environment if needed |
|||
CUDA_AVAILABLE=0 |
|||
if [ -z "$CUDA_HOME" ]; then |
|||
if [ -d "/usr/local/cuda" ]; then |
|||
export CUDA_HOME=/usr/local/cuda |
|||
CUDA_AVAILABLE=1 |
|||
elif [ -d "/usr/lib/cuda" ]; then |
|||
export CUDA_HOME=/usr/lib/cuda |
|||
CUDA_AVAILABLE=1 |
|||
fi |
|||
# Verify CUDA version from specified CUDA_HOME |
|||
NVCC_PATH="${CUDA_HOME}/bin/nvcc" |
|||
if ! [ -x "${NVCC_PATH}" ]; then |
|||
echo "Error: NVCC not found at specified path: ${NVCC_PATH}" >&2 |
|||
echo "Please ensure CUDA_HOME is set correctly and NVCC is executable." >&2 |
|||
exit 1 |
|||
fi |
|||
DETECTED_CUDA_RUNTIME_VERSION=$(${NVCC_PATH} --version | grep "release" | awk '{print $6}' | cut -c2- | cut -d'.' -f1-2) |
|||
echo "Detected CUDA Runtime version (from ${NVCC_PATH}): $DETECTED_CUDA_RUNTIME_VERSION" |
|||
|
|||
# Add CUDA to path if available |
|||
if [ $CUDA_AVAILABLE -eq 1 ]; then |
|||
echo "CUDA found at $CUDA_HOME" |
|||
export PATH=$CUDA_HOME/bin:$PATH |
|||
export LD_LIBRARY_PATH=$CUDA_HOME/lib64:$LD_LIBRARY_PATH |
|||
# Target LibTorch 1.8.0+cu111 to match Python environment |
|||
LIBTORCH_VARIANT="cxx11-abi-shared-with-deps" # For shared libraries with dependencies |
|||
LIBTORCH_DIR_NAME="libtorch_${LIBTORCH_VERSION}_${LIBTORCH_CUDA_VERSION_SHORT}" |
|||
LIBTORCH_INSTALL_PATH="$HOME/${LIBTORCH_DIR_NAME}/libtorch" |
|||
LIBTORCH_ZIP_URL="https://download.pytorch.org/libtorch/${LIBTORCH_CUDA_VERSION_SHORT}/libtorch-${LIBTORCH_VARIANT}-${LIBTORCH_VERSION}%2B${LIBTORCH_CUDA_VERSION_SHORT}.zip" |
|||
EXPECTED_LIBTORCH_CMAKE_CONFIG="${LIBTORCH_INSTALL_PATH}/share/cmake/Torch/TorchConfig.cmake" |
|||
|
|||
# Determine CUDA version |
|||
CUDA_VERSION=$(nvcc --version | grep "release" | awk '{print $6}' | cut -c2- | cut -d'.' -f1-2) |
|||
echo "Detected CUDA version: $CUDA_VERSION" |
|||
else |
|||
echo "CUDA not found. The project requires CUDA to build." |
|||
echo "Please install CUDA and try again." |
|||
exit 1 |
|||
fi |
|||
echo "Targeting LibTorch ${LIBTORCH_VERSION}+${LIBTORCH_CUDA_VERSION_SHORT}" |
|||
|
|||
# Download and extract LibTorch with appropriate CUDA support if not already present |
|||
LIBTORCH_DIR="$HOME/libtorch" |
|||
if [ ! -d "$LIBTORCH_DIR" ]; then |
|||
echo "Downloading LibTorch..." |
|||
# Use a compatible version based on detected CUDA |
|||
echo "Downloading CUDA-enabled LibTorch" |
|||
if [[ "$CUDA_VERSION" == "11.5" || "$CUDA_VERSION" == "11.6" || "$CUDA_VERSION" == "11.7" ]]; then |
|||
LIBTORCH_URL="https://download.pytorch.org/libtorch/cu116/libtorch-cxx11-abi-shared-with-deps-1.13.0%2Bcu116.zip" |
|||
elif [[ "$CUDA_VERSION" == "11.3" || "$CUDA_VERSION" == "11.4" ]]; then |
|||
LIBTORCH_URL="https://download.pytorch.org/libtorch/cu113/libtorch-cxx11-abi-shared-with-deps-1.12.1%2Bcu113.zip" |
|||
if [ ! -f "$EXPECTED_LIBTORCH_CMAKE_CONFIG" ]; then |
|||
echo "LibTorch ${LIBTORCH_VERSION}+${LIBTORCH_CUDA_VERSION_SHORT} not found at ${LIBTORCH_INSTALL_PATH}." |
|||
TMP_DIR=$(mktemp -d) |
|||
echo "Downloading LibTorch ${LIBTORCH_VERSION}+${LIBTORCH_CUDA_VERSION_SHORT}..." |
|||
echo "Using LibTorch URL: ${LIBTORCH_ZIP_URL}" |
|||
wget -q -O "${TMP_DIR}/libtorch.zip" "${LIBTORCH_ZIP_URL}" |
|||
echo "Extracting LibTorch to $HOME/${LIBTORCH_DIR_NAME}..." |
|||
mkdir -p "$HOME/${LIBTORCH_DIR_NAME}" |
|||
unzip -q "${TMP_DIR}/libtorch.zip" -d "$HOME/${LIBTORCH_DIR_NAME}" |
|||
rm -rf "${TMP_DIR}" |
|||
if [ -f "$EXPECTED_LIBTORCH_CMAKE_CONFIG" ]; then |
|||
echo "LibTorch ${LIBTORCH_VERSION}+${LIBTORCH_CUDA_VERSION_SHORT} extracted to ${LIBTORCH_INSTALL_PATH}" |
|||
else |
|||
LIBTORCH_URL="https://download.pytorch.org/libtorch/cu118/libtorch-cxx11-abi-shared-with-deps-2.0.0%2Bcu118.zip" |
|||
echo "Error: LibTorch extraction failed or TorchConfig.cmake not found at expected location: $EXPECTED_LIBTORCH_CMAKE_CONFIG" |
|||
exit 1 |
|||
fi |
|||
|
|||
wget $LIBTORCH_URL -O libtorch.zip |
|||
echo "Extracting LibTorch..." |
|||
mkdir -p $HOME |
|||
unzip -q libtorch.zip -d $HOME |
|||
rm libtorch.zip |
|||
echo "LibTorch extracted to $LIBTORCH_DIR" |
|||
else |
|||
echo "Using existing LibTorch installation at $LIBTORCH_DIR" |
|||
echo "Found existing LibTorch ${LIBTORCH_VERSION}+${LIBTORCH_CUDA_VERSION_SHORT} at ${LIBTORCH_INSTALL_PATH}" |
|||
fi |
|||
|
|||
# Create build directory |
|||
mkdir -p build |
|||
cd build |
|||
# Set Torch_DIR for CMake |
|||
export Torch_DIR="${LIBTORCH_INSTALL_PATH}/share/cmake/Torch" |
|||
|
|||
# Build directory |
|||
BUILD_DIR="build" |
|||
mkdir -p "${BUILD_DIR}" |
|||
cd "${BUILD_DIR}" |
|||
|
|||
# Create local bin directory |
|||
mkdir -p ../bin |
|||
# Relative path to vcpkg.cmake from the build directory if vcpkg is a submodule in the project root |
|||
# This assumes vcpkg is at ../vcpkg (relative to build dir) or ./vcpkg (relative to project root) |
|||
VCPKG_TOOLCHAIN_FILE_PROJECT_SUBMODULE="../vcpkg/scripts/buildsystems/vcpkg.cmake" |
|||
VCPKG_TOOLCHAIN_FILE_BUILD_SUBDIR="vcpkg/scripts/buildsystems/vcpkg.cmake" # if vcpkg is cloned into build dir by CMake |
|||
|
|||
CMAKE_TOOLCHAIN_ARG="" |
|||
if [ -f "$VCPKG_TOOLCHAIN_FILE_PROJECT_SUBMODULE" ]; then |
|||
echo "Using vcpkg toolchain: $VCPKG_TOOLCHAIN_FILE_PROJECT_SUBMODULE (relative to build dir)" |
|||
CMAKE_TOOLCHAIN_ARG="-DCMAKE_TOOLCHAIN_FILE=$VCPKG_TOOLCHAIN_FILE_PROJECT_SUBMODULE" |
|||
elif [ -f "$VCPKG_TOOLCHAIN_FILE_BUILD_SUBDIR" ]; then # this case is less common for user setup |
|||
echo "Using vcpkg toolchain: $VCPKG_TOOLCHAIN_FILE_BUILD_SUBDIR (relative to build dir)" |
|||
CMAKE_TOOLCHAIN_ARG="-DCMAKE_TOOLCHAIN_FILE=$VCPKG_TOOLCHAIN_FILE_BUILD_SUBDIR" |
|||
else |
|||
echo "vcpkg.cmake not found at common project submodule paths. CMake will try to find it via vcpkg.json if vcpkg is globally installed and configured." |
|||
# If vcpkg is globally installed and CMAKE_TOOLCHAIN_FILE is set in user's environment, CMake might pick it up. |
|||
# Or, if CMake has native vcpkg integration via CMAKE_PROJECT_TOP_LEVEL_INCLUDES with vcpkg.cmake. |
|||
fi |
|||
|
|||
# Configure with CMake - always use CUDA, never use CPU_ONLY |
|||
echo "Configuring with CMake..." |
|||
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=.. -DCPU_ONLY=OFF |
|||
# Pass the CMAKE_TOOLCHAIN_FILE to cmake. |
|||
# The Torch_DIR is already exported. |
|||
cmake .. -DCMAKE_BUILD_TYPE=Release ${CMAKE_TOOLCHAIN_ARG} |
|||
|
|||
# Build the project |
|||
echo "Building the project..." |
|||
cmake --build . --config Release -j $(nproc) |
|||
echo "Building..." |
|||
cmake --build . --config Release -- -j$(nproc) |
|||
|
|||
# Install to local directory |
|||
echo "Installing to local bin directory..." |
|||
cmake --install . --config Release |
|||
echo "Build complete." |
|||
cd .. |
|||
|
|||
echo "Build complete! Executable is in bin/" |
4246
build/CMakeFiles/3.22.1/CompilerIdCUDA/tmp/CMakeCUDACompilerId.cpp1.ii
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
4120
build/CMakeFiles/3.22.1/CompilerIdCUDA/tmp/CMakeCUDACompilerId.cpp4.ii
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
7546
build/CMakeFiles/3.22.1/CompilerIdCUDA/tmp/CMakeCUDACompilerId.cudafe1.cpp
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
1156
build/CMakeFiles/CMakeOutput.log
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
5157
build/CMakeFiles/bb_regressor.dir/cimp/bb_regressor/bb_regressor.cpp.o.d
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -1,13 +1,13 @@ |
|||
file(REMOVE_RECURSE |
|||
"CMakeFiles/bb_regressor.dir/cimp/bb_regressor/bb_regressor.cpp.o" |
|||
"CMakeFiles/bb_regressor.dir/cimp/bb_regressor/bb_regressor.cpp.o.d" |
|||
"CMakeFiles/bb_regressor.dir/cimp/bb_regressor/prroi_pooling/prroi_pooling_gpu.cpp.o" |
|||
"CMakeFiles/bb_regressor.dir/cimp/bb_regressor/prroi_pooling/prroi_pooling_gpu.cpp.o.d" |
|||
"CMakeFiles/bb_regressor.dir/cimp/bb_regressor/prroi_pooling/prroi_pooling_gpu_impl.cu.o" |
|||
"CMakeFiles/bb_regressor.dir/cimp/bb_regressor/prroi_pooling/prroi_pooling_gpu_impl.cu.o.d" |
|||
"libbb_regressor.a" |
|||
"libbb_regressor.pdb" |
|||
) |
|||
|
|||
# Per-language clean rules from dependency scanning. |
|||
foreach(lang CXX) |
|||
foreach(lang CUDA CXX) |
|||
include(CMakeFiles/bb_regressor.dir/cmake_clean_${lang}.cmake OPTIONAL) |
|||
endforeach() |
5367
build/CMakeFiles/bb_regressor.dir/compiler_depend.internal
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
15247
build/CMakeFiles/bb_regressor.dir/compiler_depend.make
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -1,10 +1,17 @@ |
|||
# CMAKE generated file: DO NOT EDIT! |
|||
# Generated by "Unix Makefiles" Generator, CMake Version 3.22 |
|||
|
|||
# compile CUDA with /usr/local/cuda-11.8/bin/nvcc |
|||
# compile CXX with /usr/bin/c++ |
|||
CXX_DEFINES = -DUSE_C10D_GLOO -DUSE_C10D_NCCL -DUSE_DISTRIBUTED -DUSE_RPC -DUSE_TENSORPIPE |
|||
CUDA_DEFINES = |
|||
|
|||
CXX_INCLUDES = -I/media/mht/ADATA/repos/cpp_tracker/cimp -I/media/mht/ADATA/repos/cpp_tracker/cimp/bb_regressor/prroi_pooling -I/media/mht/ADATA/repos/cpp_tracker/ltr/external/PreciseRoIPooling/pytorch/prroi_pool/src -isystem /home/mht/libtorch/include -isystem /home/mht/libtorch/include/torch/csrc/api/include |
|||
CUDA_INCLUDES = -I/media/mht/ADATA/repos/cpp_tracker/cimp -I/media/mht/ADATA/repos/cpp_tracker/cimp/bb_regressor/prroi_pooling -I/media/mht/ADATA/repos/cpp_tracker/ltr/external/PreciseRoIPooling/pytorch/prroi_pool/src -isystem=/home/mht/libtorch_1.8.0_cu111/libtorch/include -isystem=/home/mht/libtorch_1.8.0_cu111/libtorch/include/torch/csrc/api/include -isystem=/usr/local/cuda-11.8/include |
|||
|
|||
CUDA_FLAGS = -O3 -DNDEBUG --generate-code=arch=compute_52,code=[compute_52,sm_52] -D_GLIBCXX_USE_CXX11_ABI=1 -std=c++17 |
|||
|
|||
CXX_DEFINES = |
|||
|
|||
CXX_INCLUDES = -I/media/mht/ADATA/repos/cpp_tracker/cimp -I/media/mht/ADATA/repos/cpp_tracker/cimp/bb_regressor/prroi_pooling -I/media/mht/ADATA/repos/cpp_tracker/ltr/external/PreciseRoIPooling/pytorch/prroi_pool/src -isystem /home/mht/libtorch_1.8.0_cu111/libtorch/include -isystem /home/mht/libtorch_1.8.0_cu111/libtorch/include/torch/csrc/api/include -isystem /usr/local/cuda-11.8/include |
|||
|
|||
CXX_FLAGS = -O3 -DNDEBUG -D_GLIBCXX_USE_CXX11_ABI=1 -std=gnu++17 |
|||
|
@ -1,2 +1,2 @@ |
|||
/usr/bin/ar qc libbb_regressor.a CMakeFiles/bb_regressor.dir/cimp/bb_regressor/bb_regressor.cpp.o CMakeFiles/bb_regressor.dir/cimp/bb_regressor/prroi_pooling/prroi_pooling_gpu.cpp.o |
|||
/usr/bin/ar qc libbb_regressor.a CMakeFiles/bb_regressor.dir/cimp/bb_regressor/bb_regressor.cpp.o CMakeFiles/bb_regressor.dir/cimp/bb_regressor/prroi_pooling/prroi_pooling_gpu_impl.cu.o |
|||
/usr/bin/ranlib libbb_regressor.a |
5088
build/CMakeFiles/classifier.dir/cimp/classifier/classifier.cpp.o.d
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
5123
build/CMakeFiles/classifier.dir/compiler_depend.internal
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
14799
build/CMakeFiles/classifier.dir/compiler_depend.make
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
4910
build/CMakeFiles/tracking_demo.dir/cimp/demo.cpp.o.d
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
2148
build/CMakeFiles/tracking_demo.dir/compiler_depend.make
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -1 +1 @@ |
|||
/usr/bin/c++ -O3 -DNDEBUG CMakeFiles/tracking_demo.dir/cimp/demo.cpp.o -o tracking_demo -Wl,-rpath,/home/mht/libtorch/lib: libbb_regressor.a libclassifier.a /home/mht/libtorch/lib/libtorch.so /home/mht/libtorch/lib/libc10.so /home/mht/libtorch/lib/libkineto.a /usr/lib/x86_64-linux-gnu/libcuda.so /usr/lib/x86_64-linux-gnu/libnvrtc.so /usr/lib/x86_64-linux-gnu/libnvToolsExt.so /usr/lib/x86_64-linux-gnu/libcudart.so /home/mht/libtorch/lib/libc10_cuda.so -Wl,--no-as-needed,"/home/mht/libtorch/lib/libtorch_cpu.so" -Wl,--as-needed -Wl,--no-as-needed,"/home/mht/libtorch/lib/libtorch_cuda.so" -Wl,--as-needed /home/mht/libtorch/lib/libc10_cuda.so /home/mht/libtorch/lib/libc10.so /usr/lib/x86_64-linux-gnu/libcufft.so /usr/lib/x86_64-linux-gnu/libcurand.so /usr/lib/x86_64-linux-gnu/libcublas.so /usr/lib/x86_64-linux-gnu/libcublasLt.so -Wl,--no-as-needed,"/home/mht/libtorch/lib/libtorch.so" -Wl,--as-needed /usr/lib/x86_64-linux-gnu/libnvToolsExt.so /usr/lib/x86_64-linux-gnu/libcudart.so |
|||
/usr/bin/c++ -O3 -DNDEBUG CMakeFiles/tracking_demo.dir/cimp/demo.cpp.o -o tracking_demo -L/usr/local/cuda-11.8/targets/x86_64-linux/lib/stubs -L/usr/local/cuda-11.8/targets/x86_64-linux/lib -Wl,-rpath,/home/mht/libtorch_1.8.0_cu111/libtorch/lib:/usr/local/cuda-11.8/lib64/stubs:/usr/local/cuda-11.8/lib64: libbb_regressor.a libclassifier.a libresnet.a /home/mht/libtorch_1.8.0_cu111/libtorch/lib/libtorch.so /home/mht/libtorch_1.8.0_cu111/libtorch/lib/libc10.so /usr/local/cuda-11.8/lib64/stubs/libcuda.so /usr/local/cuda-11.8/lib64/libnvrtc.so /usr/local/cuda-11.8/lib64/libnvToolsExt.so /usr/local/cuda-11.8/lib64/libcudart.so /home/mht/libtorch_1.8.0_cu111/libtorch/lib/libc10_cuda.so -Wl,--no-as-needed,"/home/mht/libtorch_1.8.0_cu111/libtorch/lib/libtorch_cuda.so" -Wl,--as-needed -Wl,--no-as-needed,"/home/mht/libtorch_1.8.0_cu111/libtorch/lib/libtorch_cuda_cu.so" -Wl,--as-needed -Wl,--no-as-needed,"/home/mht/libtorch_1.8.0_cu111/libtorch/lib/libtorch_cpu.so" -Wl,--as-needed /home/mht/libtorch_1.8.0_cu111/libtorch/lib/libc10_cuda.so /home/mht/libtorch_1.8.0_cu111/libtorch/lib/libc10.so /usr/local/cuda-11.8/lib64/libcufft.so /usr/local/cuda-11.8/lib64/libcurand.so /usr/local/cuda-11.8/lib64/libcublas.so /usr/lib/x86_64-linux-gnu/libcudnn.so -Wl,--no-as-needed,"/home/mht/libtorch_1.8.0_cu111/libtorch/lib/libtorch_cuda_cpp.so" -Wl,--as-needed -Wl,--no-as-needed,"/home/mht/libtorch_1.8.0_cu111/libtorch/lib/libtorch.so" -Wl,--as-needed /usr/local/cuda-11.8/lib64/libnvToolsExt.so /usr/local/cuda-11.8/lib64/libcudart.so -lcudadevrt -lcudart_static -lrt -lpthread -ldl |
@ -1,3 +1,2 @@ |
|||
/media/mht/ADATA/repos/cpp_tracker/bin/tracking_demo |
|||
/media/mht/ADATA/repos/cpp_tracker/bin/test_models |
|||
/media/mht/ADATA/repos/cpp_tracker/bin/generate_test_samples |
|||
/media/mht/ADATA/repos/cpp_tracker/bin/test_models |
@ -0,0 +1,287 @@ |
|||
#include "resnet.h"
|
|||
#include <filesystem> // For std::filesystem::path
|
|||
#include <stdexcept> // For std::runtime_error
|
|||
#include <torch/script.h> // For torch::jit::load and torch::jit::Module
|
|||
#include <optional> // ensure this is included
|
|||
#include <fstream> // Added for std::ifstream
|
|||
#include <vector> // Added for std::vector
|
|||
|
|||
namespace cimp { |
|||
namespace resnet { |
|||
|
|||
namespace fs = std::filesystem; // Moved fs namespace alias here
|
|||
|
|||
// Helper function to load a tensor by its parameter name (e.g., "conv1.weight")
|
|||
// Assumes .pt files are named like "conv1.weight.pt", "layer1.0.bn1.running_mean.pt"
|
|||
torch::Tensor load_named_tensor(const std::string& base_weights_dir, const std::string& param_name_original, const torch::Device& device) { |
|||
fs::path tensor_file_path = fs::path(base_weights_dir) / (param_name_original + ".pt"); |
|||
|
|||
if (!fs::exists(tensor_file_path)) { |
|||
std::string param_name_underscore = param_name_original; |
|||
std::replace(param_name_underscore.begin(), param_name_underscore.end(), '.', '_'); |
|||
fs::path tensor_file_path_underscore = fs::path(base_weights_dir) / (param_name_underscore + ".pt"); |
|||
|
|||
if (fs::exists(tensor_file_path_underscore)) { |
|||
std::cout << "INFO: Using underscore-named file for C++ loading: " << tensor_file_path_underscore.string() << std::endl; |
|||
tensor_file_path = tensor_file_path_underscore; |
|||
} else { |
|||
throw std::runtime_error("Weight file not found (tried direct and underscore versions): " + |
|||
(fs::path(base_weights_dir) / (param_name_original + ".pt")).string() + |
|||
" and " + tensor_file_path_underscore.string()); |
|||
} |
|||
} |
|||
|
|||
std::cout << "Attempting direct torch::pickle_load for tensor: " << tensor_file_path.string() << std::endl; |
|||
try { |
|||
// Read the file into a vector<char>
|
|||
std::ifstream file_stream(tensor_file_path.string(), std::ios::binary); |
|||
if (!file_stream) { |
|||
throw std::runtime_error("Failed to open file: " + tensor_file_path.string()); |
|||
} |
|||
std::vector<char> file_buffer((std::istreambuf_iterator<char>(file_stream)), |
|||
std::istreambuf_iterator<char>()); |
|||
file_stream.close(); |
|||
|
|||
c10::IValue ivalue = torch::pickle_load(file_buffer); |
|||
return ivalue.toTensor().to(device); |
|||
} catch (const c10::Error& e) { |
|||
std::cerr << "CRITICAL ERROR: torch::pickle_load FAILED for '" << tensor_file_path.string() << "'. Error: " << e.what() << std::endl; |
|||
throw; |
|||
} |
|||
} |
|||
|
|||
// --- BottleneckImpl Method Definitions ---
|
|||
|
|||
// Constructor implementation for BottleneckImpl
|
|||
// Signature must match resnet.h:
|
|||
// BottleneckImpl(int64_t inplanes, int64_t planes, const std::string& weights_dir_prefix, int64_t stride = 1,
|
|||
// std::optional<torch::nn::Sequential> downsample_module_opt = std::nullopt, int64_t expansion_factor_arg = 4);
|
|||
BottleneckImpl::BottleneckImpl(const std::string& base_weights_dir, |
|||
const std::string& block_param_prefix, |
|||
int64_t inplanes, int64_t planes, |
|||
const torch::Device& device, |
|||
int64_t stride_param, std::optional<torch::nn::Sequential> downsample_module_opt, |
|||
int64_t expansion_factor_arg) |
|||
: expansion_factor(expansion_factor_arg), stride_member(stride_param) { |
|||
|
|||
// conv1
|
|||
conv1 = torch::nn::Conv2d(torch::nn::Conv2dOptions(inplanes, planes, 1).bias(false)); |
|||
bn1 = torch::nn::BatchNorm2d(torch::nn::BatchNorm2dOptions(planes)); |
|||
conv1->weight = load_named_tensor(base_weights_dir, block_param_prefix + "conv1.weight", device); |
|||
bn1->weight = load_named_tensor(base_weights_dir, block_param_prefix + "bn1.weight", device); |
|||
bn1->bias = load_named_tensor(base_weights_dir, block_param_prefix + "bn1.bias", device); |
|||
bn1->named_buffers()["running_mean"] = load_named_tensor(base_weights_dir, block_param_prefix + "bn1.running_mean", device); |
|||
bn1->named_buffers()["running_var"] = load_named_tensor(base_weights_dir, block_param_prefix + "bn1.running_var", device); |
|||
register_module("conv1", conv1); |
|||
register_module("bn1", bn1); |
|||
|
|||
// conv2
|
|||
conv2 = torch::nn::Conv2d(torch::nn::Conv2dOptions(planes, planes, 3).stride(stride_member).padding(1).bias(false)); |
|||
bn2 = torch::nn::BatchNorm2d(torch::nn::BatchNorm2dOptions(planes)); |
|||
conv2->weight = load_named_tensor(base_weights_dir, block_param_prefix + "conv2.weight", device); |
|||
bn2->weight = load_named_tensor(base_weights_dir, block_param_prefix + "bn2.weight", device); |
|||
bn2->bias = load_named_tensor(base_weights_dir, block_param_prefix + "bn2.bias", device); |
|||
bn2->named_buffers()["running_mean"] = load_named_tensor(base_weights_dir, block_param_prefix + "bn2.running_mean", device); |
|||
bn2->named_buffers()["running_var"] = load_named_tensor(base_weights_dir, block_param_prefix + "bn2.running_var", device); |
|||
register_module("conv2", conv2); |
|||
register_module("bn2", bn2); |
|||
|
|||
// conv3
|
|||
conv3 = torch::nn::Conv2d(torch::nn::Conv2dOptions(planes, planes * expansion_factor, 1).bias(false)); |
|||
bn3 = torch::nn::BatchNorm2d(torch::nn::BatchNorm2dOptions(planes * expansion_factor)); |
|||
conv3->weight = load_named_tensor(base_weights_dir, block_param_prefix + "conv3.weight", device); |
|||
bn3->weight = load_named_tensor(base_weights_dir, block_param_prefix + "bn3.weight", device); |
|||
bn3->bias = load_named_tensor(base_weights_dir, block_param_prefix + "bn3.bias", device); |
|||
bn3->named_buffers()["running_mean"] = load_named_tensor(base_weights_dir, block_param_prefix + "bn3.running_mean", device); |
|||
bn3->named_buffers()["running_var"] = load_named_tensor(base_weights_dir, block_param_prefix + "bn3.running_var", device); |
|||
register_module("conv3", conv3); |
|||
register_module("bn3", bn3); |
|||
|
|||
relu = torch::nn::ReLU(torch::nn::ReLUOptions(true)); |
|||
register_module("relu", relu); |
|||
|
|||
if (downsample_module_opt.has_value()) { |
|||
this->projection_shortcut = downsample_module_opt.value(); // Assign the passed Sequential module
|
|||
|
|||
// Weights for the submodules of projection_shortcut (conv & bn) are loaded by _make_layer
|
|||
// before this module is passed. Here, we just register it.
|
|||
register_module("projection_shortcut", this->projection_shortcut); |
|||
} else { |
|||
this->projection_shortcut = nullptr; |
|||
} |
|||
} |
|||
|
|||
// Forward method implementation for BottleneckImpl
|
|||
torch::Tensor BottleneckImpl::forward(torch::Tensor x) { |
|||
torch::Tensor identity = x; |
|||
|
|||
x = conv1->forward(x); |
|||
x = bn1->forward(x); |
|||
x = relu->forward(x); |
|||
|
|||
x = conv2->forward(x); |
|||
x = bn2->forward(x); |
|||
x = relu->forward(x); |
|||
|
|||
x = conv3->forward(x); |
|||
x = bn3->forward(x); |
|||
|
|||
if (this->projection_shortcut) { |
|||
identity = this->projection_shortcut->forward(identity); |
|||
} |
|||
|
|||
x += identity; |
|||
x = relu->forward(x); |
|||
|
|||
return x; |
|||
} |
|||
|
|||
// --- ResNetImpl Method Definitions ---
|
|||
ResNetImpl::ResNetImpl(const std::string& base_weights_dir_path, |
|||
const std::vector<int64_t>& layers_dims, |
|||
const std::vector<std::string>& output_layers_param, |
|||
const torch::Device& device) |
|||
: _output_layers(output_layers_param), _base_weights_dir(base_weights_dir_path) { |
|||
|
|||
conv1 = torch::nn::Conv2d(torch::nn::Conv2dOptions(3, 64, 7).stride(2).padding(3).bias(false)); |
|||
bn1 = torch::nn::BatchNorm2d(torch::nn::BatchNorm2dOptions(64)); |
|||
this->conv1->weight = load_named_tensor(this->_base_weights_dir, "conv1.weight", device); |
|||
this->bn1->weight = load_named_tensor(this->_base_weights_dir, "bn1.weight", device); |
|||
this->bn1->bias = load_named_tensor(this->_base_weights_dir, "bn1.bias", device); |
|||
this->bn1->named_buffers()["running_mean"] = load_named_tensor(this->_base_weights_dir, "bn1.running_mean", device); |
|||
this->bn1->named_buffers()["running_var"] = load_named_tensor(this->_base_weights_dir, "bn1.running_var", device); |
|||
register_module("conv1", conv1); |
|||
register_module("bn1", bn1); |
|||
|
|||
relu = torch::nn::ReLU(torch::nn::ReLUOptions().inplace(true)); |
|||
maxpool = torch::nn::MaxPool2d(torch::nn::MaxPool2dOptions(3).stride(2).padding(1)); |
|||
register_module("relu", relu); |
|||
register_module("maxpool", maxpool); |
|||
|
|||
layer1 = _make_layer(64, layers_dims[0], "layer1.", device); |
|||
layer2 = _make_layer(128, layers_dims[1], "layer2.", device, 2); |
|||
layer3 = _make_layer(256, layers_dims[2], "layer3.", device, 2); |
|||
layer4 = _make_layer(512, layers_dims[3], "layer4.", device, 2); |
|||
register_module("layer1", layer1); |
|||
register_module("layer2", layer2); |
|||
register_module("layer3", layer3); |
|||
register_module("layer4", layer4); |
|||
} |
|||
|
|||
torch::nn::Sequential ResNetImpl::_make_layer(int64_t planes_for_block, int64_t num_blocks, |
|||
const std::string& layer_param_prefix, |
|||
const torch::Device& device, |
|||
int64_t stride_for_first_block) { |
|||
torch::nn::Sequential layer_sequential; |
|||
std::optional<torch::nn::Sequential> downsample_module_for_block_opt = std::nullopt; |
|||
|
|||
if (stride_for_first_block != 1 || this->inplanes != planes_for_block * ResNetImpl::expansion) { |
|||
torch::nn::Sequential ds_seq; |
|||
auto conv_down = torch::nn::Conv2d(torch::nn::Conv2dOptions(this->inplanes, planes_for_block * ResNetImpl::expansion, 1).stride(stride_for_first_block).bias(false)); |
|||
auto bn_down = torch::nn::BatchNorm2d(torch::nn::BatchNorm2dOptions(planes_for_block * ResNetImpl::expansion)); |
|||
|
|||
std::string ds_block_prefix = layer_param_prefix + "0.downsample."; |
|||
|
|||
conv_down->weight = load_named_tensor(this->_base_weights_dir, ds_block_prefix + "0.weight", device); |
|||
bn_down->weight = load_named_tensor(this->_base_weights_dir, ds_block_prefix + "1.weight", device); |
|||
bn_down->bias = load_named_tensor(this->_base_weights_dir, ds_block_prefix + "1.bias", device); |
|||
bn_down->named_buffers()["running_mean"] = load_named_tensor(this->_base_weights_dir, ds_block_prefix + "1.running_mean", device); |
|||
bn_down->named_buffers()["running_var"] = load_named_tensor(this->_base_weights_dir, ds_block_prefix + "1.running_var", device); |
|||
|
|||
ds_seq->push_back(conv_down); |
|||
ds_seq->push_back(bn_down); |
|||
downsample_module_for_block_opt = ds_seq; |
|||
} |
|||
|
|||
std::string first_block_param_prefix = layer_param_prefix + "0."; |
|||
layer_sequential->push_back(Bottleneck(this->_base_weights_dir, first_block_param_prefix, |
|||
this->inplanes, planes_for_block, device, |
|||
stride_for_first_block, |
|||
downsample_module_for_block_opt, ResNetImpl::expansion)); |
|||
this->inplanes = planes_for_block * ResNetImpl::expansion; |
|||
|
|||
for (int64_t i = 1; i < num_blocks; ++i) { |
|||
std::string current_block_param_prefix = layer_param_prefix + std::to_string(i) + "."; |
|||
layer_sequential->push_back(Bottleneck(this->_base_weights_dir, current_block_param_prefix, |
|||
this->inplanes, planes_for_block, device, |
|||
1, |
|||
std::nullopt, ResNetImpl::expansion)); |
|||
} |
|||
return layer_sequential; |
|||
} |
|||
|
|||
std::map<std::string, torch::Tensor> ResNetImpl::forward(torch::Tensor x) { |
|||
std::map<std::string, torch::Tensor> outputs; |
|||
auto should_output = [&](const std::string& layer_name) { |
|||
return std::find(_output_layers.begin(), _output_layers.end(), layer_name) != _output_layers.end(); |
|||
}; |
|||
|
|||
// Original GPU path for conv1
|
|||
x = conv1->forward(x); |
|||
if (should_output("conv1_output")) outputs["conv1_output"] = x; |
|||
|
|||
x = bn1->forward(x.clone()); |
|||
if (should_output("bn1_output")) outputs["bn1_output"] = x; |
|||
|
|||
x = relu->forward(x.clone()); |
|||
if (should_output("relu1_output")) outputs["relu1_output"] = x; |
|||
|
|||
torch::Tensor x_pre_layer1 = maxpool->forward(x.clone()); |
|||
if (should_output("maxpool_output")) outputs["maxpool_output"] = x_pre_layer1; |
|||
|
|||
// Pass x_pre_layer1 to layer1
|
|||
torch::Tensor x_after_layer1 = layer1->forward(x_pre_layer1.clone()); // Use .clone() if layer1 might modify input inplace, good practice
|
|||
if (should_output("layer1")) outputs["layer1"] = x_after_layer1; |
|||
|
|||
if (should_output("layer1_0_shortcut_output")) { |
|||
if (layer1 && !layer1->is_empty()) { |
|||
try { |
|||
// Get the first module (Bottleneck) from layer1 Sequential container
|
|||
std::shared_ptr<torch::nn::Module> first_block_module_ptr = layer1->ptr(0); |
|||
// Attempt to dynamically cast to Bottleneck type
|
|||
auto bottleneck_module_holder = std::dynamic_pointer_cast<cimp::resnet::BottleneckImpl>(first_block_module_ptr); |
|||
|
|||
if (bottleneck_module_holder) { // Check if cast was successful
|
|||
// Accessing projection_shortcut directly from BottleneckImpl
|
|||
if (bottleneck_module_holder->projection_shortcut) { |
|||
torch::Tensor shortcut_out = bottleneck_module_holder->projection_shortcut->forward(x_pre_layer1.clone()); |
|||
outputs["layer1_0_shortcut_output"] = shortcut_out; |
|||
} else { |
|||
// std::cout << "DEBUG: layer1.0 projection_shortcut is null." << std::endl;
|
|||
} |
|||
} else { |
|||
// std::cerr << "ERROR: Failed to cast first block of layer1 to BottleneckImpl." << std::endl;
|
|||
} |
|||
} catch (const std::exception& e) { |
|||
// std::cerr << "ERROR: Exception while getting layer1_0_shortcut_output: " << e.what() << std::endl;
|
|||
} |
|||
} else { |
|||
// std::cout << "DEBUG: layer1 is null or empty, cannot get shortcut output." << std::endl;
|
|||
} |
|||
} |
|||
|
|||
torch::Tensor x_current = x_after_layer1; // Continue with the output of layer1
|
|||
|
|||
x_current = layer2->forward(x_current.clone()); |
|||
if (should_output("layer2")) outputs["layer2"] = x_current; |
|||
|
|||
x_current = layer3->forward(x_current.clone()); |
|||
if (should_output("layer3")) outputs["layer3"] = x_current; |
|||
|
|||
x_current = layer4->forward(x_current.clone()); |
|||
if (should_output("layer4")) outputs["layer4"] = x_current; |
|||
|
|||
if (should_output("features")) outputs["features"] = x_current; // 'features' is typically layer4 output
|
|||
|
|||
return outputs; |
|||
} |
|||
|
|||
// For ResNet-50, layers are [3, 4, 6, 3]
|
|||
ResNet resnet50(const std::string& base_weights_dir, |
|||
const std::vector<std::string>& output_layers, |
|||
const torch::Device& device) { |
|||
return ResNet(ResNetImpl(base_weights_dir, {3, 4, 6, 3}, output_layers, device)); // Pass device
|
|||
} |
|||
|
|||
} // namespace resnet
|
|||
} // namespace cimp
|
@ -0,0 +1,82 @@ |
|||
#ifndef CPP_TRACKER_RESNET_H |
|||
#define CPP_TRACKER_RESNET_H |
|||
|
|||
#include <torch/torch.h> |
|||
#include <vector> |
|||
#include <string> |
|||
#include <map> |
|||
#include <optional> |
|||
|
|||
namespace cimp { |
|||
namespace resnet { |
|||
|
|||
// ResNet-50 Bottleneck block IMPLementation |
|||
struct BottleneckImpl : torch::nn::Module { |
|||
// Constructor declaration |
|||
BottleneckImpl(const std::string& base_weights_dir, |
|||
const std::string& block_param_prefix, |
|||
int64_t inplanes, int64_t planes, |
|||
const torch::Device& device, |
|||
int64_t stride = 1, |
|||
std::optional<torch::nn::Sequential> downsample_module_opt = std::nullopt, |
|||
int64_t expansion_factor_arg = 4); |
|||
// Forward method declaration |
|||
torch::Tensor forward(torch::Tensor x); |
|||
|
|||
// Member layers (must be declared in the Impl struct) |
|||
torch::nn::Conv2d conv1{nullptr}, conv2{nullptr}, conv3{nullptr}; |
|||
torch::nn::BatchNorm2d bn1{nullptr}, bn2{nullptr}, bn3{nullptr}; |
|||
torch::nn::ReLU relu{nullptr}; |
|||
torch::nn::Sequential projection_shortcut{nullptr}; |
|||
int64_t expansion_factor; // Store the expansion factor |
|||
int64_t stride_member; // To avoid conflict with constructor param name |
|||
}; |
|||
|
|||
// This macro defines the 'Bottleneck' type based on 'BottleneckImpl' |
|||
// It effectively creates: using Bottleneck = torch::nn::ModuleHolder<BottleneckImpl>; |
|||
TORCH_MODULE(Bottleneck); |
|||
|
|||
struct ResNetImpl : torch::nn::Module { |
|||
ResNetImpl(const std::string& base_weights_dir, |
|||
const std::vector<int64_t>& layers, |
|||
const std::vector<std::string>& output_layers, |
|||
const torch::Device& device); |
|||
|
|||
std::map<std::string, torch::Tensor> forward(torch::Tensor x); |
|||
|
|||
// Initial layers |
|||
torch::nn::Conv2d conv1{nullptr}; |
|||
torch::nn::BatchNorm2d bn1{nullptr}; |
|||
torch::nn::ReLU relu{nullptr}; |
|||
torch::nn::MaxPool2d maxpool{nullptr}; |
|||
|
|||
// ResNet layers |
|||
torch::nn::Sequential layer1{nullptr}; |
|||
torch::nn::Sequential layer2{nullptr}; |
|||
torch::nn::Sequential layer3{nullptr}; |
|||
torch::nn::Sequential layer4{nullptr}; // We'll build it, even if not always outputting |
|||
|
|||
private: |
|||
torch::nn::Sequential _make_layer(int64_t planes, int64_t blocks, |
|||
const std::string& layer_param_prefix, |
|||
const torch::Device& device, |
|||
int64_t stride = 1); |
|||
int64_t inplanes = 64; |
|||
std::vector<std::string> _output_layers; |
|||
std::string _base_weights_dir; // Store base weights directory, e.g. ../exported_weights/raw_backbone |
|||
|
|||
static const int expansion = 4; // Bottleneck expansion factor for ResNet layers |
|||
}; |
|||
|
|||
TORCH_MODULE(ResNet); |
|||
|
|||
// Factory function for ResNet-50 |
|||
ResNet resnet50(const std::string& base_weights_dir, |
|||
const std::vector<std::string>& output_layers, |
|||
const torch::Device& device); |
|||
|
|||
|
|||
} // namespace resnet |
|||
} // namespace cimp |
|||
|
|||
#endif //CPP_TRACKER_RESNET_H |
@ -1,14 +1,9 @@ |
|||
/home/mht/.local/share/JetBrains/Toolbox/apps/clion/bin/cmake/linux/x64/bin/cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_MAKE_PROGRAM=/home/mht/.local/share/JetBrains/Toolbox/apps/clion/bin/ninja/linux/x64/ninja -DCMAKE_TOOLCHAIN_FILE=/media/mht/ADATA/repos/cpp_tracker/vcpkg//scripts/buildsystems/vcpkg.cmake -G Ninja -S /media/mht/ADATA/repos/cpp_tracker -B /media/mht/ADATA/repos/cpp_tracker/cmake-build-debug |
|||
-- Running vcpkg install |
|||
/media/mht/ADATA/repos/cpp_tracker/vcpkg/ports/torch: error: torch does not exist |
|||
-- Running vcpkg install - failed |
|||
CMake Error at vcpkg/scripts/buildsystems/vcpkg.cmake:938 (message): |
|||
vcpkg install failed. See logs for more information: |
|||
/media/mht/ADATA/repos/cpp_tracker/cmake-build-debug/vcpkg-manifest-install.log |
|||
/home/mht/.local/share/JetBrains/Toolbox/apps/clion/bin/cmake/linux/x64/bin/cmake -DCMAKE_BUILD_TYPE=Debug -G "Unix Makefiles" -S /media/mht/ADATA/repos/cpp_tracker -B /media/mht/ADATA/repos/cpp_tracker/cmake-build-debug |
|||
CMake Error at /home/mht/.local/share/JetBrains/Toolbox/apps/clion/bin/cmake/linux/x64/share/cmake-3.30/Modules/Internal/CMakeCUDAArchitecturesValidate.cmake:7 (message): |
|||
CMAKE_CUDA_ARCHITECTURES must be non-empty if set. |
|||
Call Stack (most recent call first): |
|||
/home/mht/.local/share/JetBrains/Toolbox/apps/clion/bin/cmake/linux/x64/share/cmake-3.30/Modules/CMakeDetermineSystem.cmake:146 (include) |
|||
/home/mht/.local/share/JetBrains/Toolbox/apps/clion/bin/cmake/linux/x64/share/cmake-3.30/Modules/CMakeDetermineCUDACompiler.cmake:112 (cmake_cuda_architectures_validate) |
|||
CMakeLists.txt:2 (project) |
|||
|
|||
|
|||
CMake Error: CMAKE_CXX_COMPILER not set, after EnableLanguage |
|||
-- Configuring incomplete, errors occurred! |
@ -0,0 +1,178 @@ |
|||
import torch |
|||
import torchvision.models as models |
|||
import os |
|||
from collections import OrderedDict |
|||
|
|||
def export_weights(model, output_dir, doc_filename): |
|||
""" |
|||
Exports model weights as individual .pt files and creates a documentation file. |
|||
Each tensor in the model's state_dict is saved. |
|||
Filename convention: replaces '.' in state_dict keys with '_', appends '.pt'. |
|||
""" |
|||
if not os.path.exists(output_dir): |
|||
os.makedirs(output_dir) |
|||
print(f"Created directory: {output_dir}") |
|||
|
|||
doc_lines = ["# Auto-generated weights documentation\n"] |
|||
state_dict = model.state_dict() |
|||
|
|||
print(f"Exporting {len(state_dict)} tensors to {output_dir}...") |
|||
|
|||
for key, tensor_data in state_dict.items(): |
|||
# Use underscore naming convention for filename, matching DiMPTorchScriptWrapper expectations |
|||
file_name = key.replace('.', '_') + '.pt' |
|||
file_path = os.path.join(output_dir, file_name) |
|||
|
|||
# Save the tensor |
|||
torch.save(tensor_data.clone().detach().cpu(), file_path) |
|||
|
|||
# Add entry to documentation file |
|||
doc_lines.append(f"## {key}\n") |
|||
doc_lines.append(f"Shape: {list(tensor_data.shape)}\n") |
|||
doc_lines.append(f"Dtype: {tensor_data.dtype}\n") |
|||
doc_lines.append(f"File: {file_name}\n\n") |
|||
|
|||
if (len(doc_lines) % 50) == 0: # Print progress periodically |
|||
print(f" Processed {len(doc_lines)//4} tensors...") |
|||
|
|||
|
|||
doc_file_path = os.path.join(output_dir, doc_filename) |
|||
with open(doc_file_path, 'w') as f: |
|||
f.writelines(doc_lines) |
|||
|
|||
print(f"Successfully exported {len(state_dict)} tensors.") |
|||
print(f"Documentation file created: {doc_file_path}") |
|||
|
|||
if __name__ == "__main__": |
|||
# --- Configuration --- |
|||
# For ResNet-50, the original DiMP seems to use a ResNet variant that might not |
|||
# exactly match torchvision's default ResNet-50 in terms of all parameter names |
|||
# or structure, especially if it was modified for specific feature extraction. |
|||
# The ltr.models.backbone.resnet.resnet50 is the one used by DiMPTorchScriptWrapper. |
|||
# We need to ensure the keys from this model are used for saving, so that |
|||
# DiMPTorchScriptWrapper can load them correctly. |
|||
|
|||
print("Loading reference ResNet-50 model structure (ltr.models.backbone.resnet)...") |
|||
# This import assumes your project structure allows this script to find ltr |
|||
# You might need to adjust sys.path if this script is placed outside the main project tree |
|||
# For example, if cpp_tracker is the root: |
|||
import sys |
|||
# Assuming this script is in cpp_tracker/ or cpp_tracker/test/ |
|||
# Adjust based on actual location if needed. |
|||
# If script is in cpp_tracker root, this is fine. |
|||
# If in cpp_tracker/test/, then '../' to get to cpp_tracker/ |
|||
project_root = os.path.dirname(os.path.abspath(__file__)) # If in root |
|||
# project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # If in a subdir like /test |
|||
# sys.path.insert(0, project_root) # Add project root to allow ltr import |
|||
|
|||
# Let's assume the script is in the root for now, or that ltr is in PYTHONPATH |
|||
try: |
|||
from ltr.models.backbone.resnet import resnet50 as ltr_resnet50 |
|||
except ImportError as e: |
|||
print(f"Error importing ltr.models.backbone.resnet: {e}") |
|||
print("Please ensure that the 'ltr' module is in your PYTHONPATH, or adjust sys.path in this script.") |
|||
print("You might need to run this script from the root of the cpp_tracker workspace or ensure correct setup.") |
|||
sys.exit(1) |
|||
|
|||
# 1. Create an instance of the LTR ResNet-50 to get the correct parameter names and structure. |
|||
# This model will define the *target* state_dict keys we want to save. |
|||
print("Instantiating LTR ResNet-50 (for structure and param names)...") |
|||
# Output_layers doesn't strictly matter here as we only need its state_dict keys, |
|||
# but use a common setting. |
|||
ltr_model = ltr_resnet50(output_layers=['layer1','layer2','layer3','layer4'], pretrained=False) |
|||
ltr_model_state_dict_keys = ltr_model.state_dict().keys() |
|||
print(f"LTR ResNet-50 instantiated. It has {len(ltr_model_state_dict_keys)} parameters/buffers.") |
|||
|
|||
# 2. Load the actual pretrained weights from torchvision. |
|||
print("Loading pretrained ResNet-50 weights from torchvision...") |
|||
torchvision_model = models.resnet50(weights=models.ResNet50_Weights.IMAGENET1K_V1) |
|||
torchvision_state_dict = torchvision_model.state_dict() |
|||
print("Torchvision ResNet-50 pretrained weights loaded.") |
|||
|
|||
# 3. Create a new state_dict that only contains keys present in *both* |
|||
# the LTR model and the torchvision model, using torchvision's weights. |
|||
# This handles potential mismatches like torchvision having a full 'fc' layer |
|||
# that the LTR ResNet variant might not use or name identically. |
|||
|
|||
# Also, ltr.models.backbone.resnet.py applies its own normalization to conv layers |
|||
# and fills batchnorm weights/biases. The torchvision pretrained=True model already has these. |
|||
# So, we directly use the torchvision weights for matching keys. |
|||
|
|||
aligned_state_dict = OrderedDict() |
|||
copied_keys = 0 |
|||
torchvision_only_keys = [] |
|||
ltr_only_keys_not_in_torchvision = [] |
|||
|
|||
for key in ltr_model_state_dict_keys: |
|||
if key in torchvision_state_dict: |
|||
if ltr_model.state_dict()[key].shape == torchvision_state_dict[key].shape: |
|||
aligned_state_dict[key] = torchvision_state_dict[key].clone() |
|||
copied_keys += 1 |
|||
else: |
|||
print(f" Shape mismatch for key '{key}': LTR shape {ltr_model.state_dict()[key].shape}, Torchvision shape {torchvision_state_dict[key].shape}. Skipping.") |
|||
ltr_only_keys_not_in_torchvision.append(key + " (shape mismatch)") |
|||
else: |
|||
# If a key from LTR model is not in torchvision, it might be an architectural difference |
|||
# or a buffer that torchvision doesn't save in its state_dict explicitly (e.g. num_batches_tracked for BN). |
|||
# The LTR model initializes these, so we can take them from the un-trained ltr_model instance. |
|||
# This is important for BN running_mean, running_var, and num_batches_tracked if not in torchvision sd. |
|||
print(f" Key '{key}' in LTR model but not in Torchvision state_dict. Using LTR model's initial value for this key.") |
|||
aligned_state_dict[key] = ltr_model.state_dict()[key].clone() # Use the initial value from ltr_model |
|||
ltr_only_keys_not_in_torchvision.append(key + " (taken from LTR init)") |
|||
copied_keys +=1 # Counting this as copied for completeness |
|||
|
|||
print(f"Matched and copied {copied_keys} Tensors from Torchvision to LTR structure.") |
|||
if ltr_only_keys_not_in_torchvision: |
|||
print(f" Keys in LTR model structure but not found in Torchvision pretrained state_dict (or shape mismatch): {len(ltr_only_keys_not_in_torchvision)}") |
|||
for k_info in ltr_only_keys_not_in_torchvision[:10]: # Print first 10 |
|||
print(f" - {k_info}") |
|||
if len(ltr_only_keys_not_in_torchvision) > 10: print(" ...") |
|||
|
|||
|
|||
for key in torchvision_state_dict.keys(): |
|||
if key not in ltr_model_state_dict_keys: |
|||
torchvision_only_keys.append(key) |
|||
|
|||
if torchvision_only_keys: |
|||
print(f" Keys in Torchvision pretrained state_dict but not in LTR model structure: {len(torchvision_only_keys)}") |
|||
for k in torchvision_only_keys[:10]: # Print first 10 |
|||
print(f" - {k}") |
|||
if len(torchvision_only_keys) > 10: print(" ...") |
|||
|
|||
|
|||
# 4. Populate the LTR model instance with these aligned weights. |
|||
# This isn't strictly necessary for saving, but it's a good check. |
|||
print("Loading aligned state_dict into LTR model instance...") |
|||
missing_keys, unexpected_keys = ltr_model.load_state_dict(aligned_state_dict, strict=False) # Use strict=False due to potential key differences |
|||
|
|||
if missing_keys: |
|||
print(f" Warning: Missing keys when loading aligned_state_dict into LTR model: {missing_keys}") |
|||
if unexpected_keys: |
|||
print(f" Warning: Unexpected keys when loading aligned_state_dict into LTR model: {unexpected_keys}") |
|||
if not missing_keys and not unexpected_keys: |
|||
print(" Successfully loaded aligned state_dict into LTR model instance.") |
|||
|
|||
|
|||
# 5. Now, use this populated ltr_model (or rather, its aligned_state_dict which has the correct keys and torchvision weights) |
|||
# for the export_weights function. The export_weights function expects a model, but we can |
|||
# give it an object that has a .state_dict() method returning our aligned_state_dict. |
|||
class TempModelWrapper: |
|||
def __init__(self, state_dict_to_serve): |
|||
self._state_dict = state_dict_to_serve |
|||
def state_dict(self): |
|||
return self._state_dict |
|||
|
|||
model_to_export_from = TempModelWrapper(aligned_state_dict) |
|||
|
|||
output_directory = "exported_weights/backbone_regenerated" |
|||
doc_file = "backbone_regenerated_weights_doc.txt" |
|||
|
|||
print(f"\nStarting export process to '{output_directory}'...") |
|||
export_weights(model_to_export_from, output_directory, doc_file) |
|||
|
|||
print("\nScript finished.") |
|||
print(f"Please check the '{output_directory}' for the .pt files and '{doc_file}'.") |
|||
print("Next steps:") |
|||
print("1. Update DiMPTorchScriptWrapper in pytracking/features/net_wrappers.py to use this new directory and doc file for ResNet.") |
|||
print("2. Update C++ ResNet loading in cimp/resnet/resnet.cpp (and test_models.cpp) to use this new directory.") |
|||
print("3. Re-run all tests (build.sh, then test/run_tests.sh).") |
@ -0,0 +1,205 @@ |
|||
import torch |
|||
import torch.nn as nn |
|||
import os |
|||
import argparse |
|||
import sys |
|||
from collections import OrderedDict |
|||
|
|||
# Add ltr to path to import ResNet |
|||
workspace_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '.')) |
|||
print(f"Workspace root: {workspace_root}") |
|||
ltr_path = os.path.join(workspace_root, 'ltr') |
|||
if not os.path.isdir(ltr_path): |
|||
print(f"Error: 'ltr' directory not found in {workspace_root}") |
|||
sys.exit(1) |
|||
sys.path.insert(0, workspace_root) |
|||
|
|||
try: |
|||
# We might not strictly need resnet50 from ltr if loading a JIT model, |
|||
# but good to have for potential type checking or structure reference. |
|||
from ltr.models.backbone.resnet import resnet50 |
|||
print("Successfully imported ResNet from ltr.models.backbone.resnet") |
|||
except ImportError as e: |
|||
print(f"Warning: Could not import ResNet from ltr.models.backbone.resnet: {e}") |
|||
# Depending on the JIT model, this might not be fatal. |
|||
|
|||
class TensorContainer(nn.Module): |
|||
def __init__(self, tensor_to_wrap, tensor_name="tensor"): |
|||
super().__init__() |
|||
# Can't use register_buffer or register_parameter as these expect string keys |
|||
# that are valid python identifiers. setattr works for general attributes. |
|||
setattr(self, tensor_name, tensor_to_wrap) |
|||
|
|||
def convert_param_name_to_filename(param_name): |
|||
"""Converts a PyTorch parameter name (e.g., layer1.0.conv1.weight) |
|||
to the underscore-separated filename convention (e.g., layer1_0_conv1_weight.pt). |
|||
""" |
|||
return param_name.replace('.', '_') + '.pt' |
|||
|
|||
def load_weights_from_individual_files(model_to_populate, source_dir): |
|||
print(f"Attempting to load weights from individual files in: {source_dir} using underscore naming convention.") |
|||
new_state_dict = OrderedDict() |
|||
loaded_count = 0 |
|||
missed_params = [] |
|||
missed_buffers = [] |
|||
|
|||
# Parameters |
|||
for name, param_tensor_template in model_to_populate.named_parameters(): |
|||
expected_filename = convert_param_name_to_filename(name) |
|||
filepath = os.path.join(source_dir, expected_filename) |
|||
|
|||
if os.path.exists(filepath): |
|||
try: |
|||
# print(f" Loading parameter: {name} from {filepath}") |
|||
tensor_data = torch.load(filepath, map_location=torch.device('cpu')) |
|||
|
|||
if isinstance(tensor_data, torch.jit.ScriptModule): |
|||
# If it's a JIT module (e.g. from previous save attempts or other sources) |
|||
# try to extract the tensor, assuming it was wrapped with a known key like 'tensor' |
|||
# or if it's a module with a single parameter/buffer. |
|||
try: |
|||
tensor_data = tensor_data.attr("tensor").toTensor() |
|||
print(f" INFO: Extracted tensor via .attr('tensor') from ScriptModule: {filepath}") |
|||
except RuntimeError: |
|||
params = list(tensor_data.parameters()) |
|||
buffers = list(tensor_data.buffers()) |
|||
if len(params) == 1: |
|||
tensor_data = params[0] |
|||
print(f" INFO: Extracted tensor from single parameter of ScriptModule: {filepath}") |
|||
elif len(buffers) == 1 and not params: |
|||
tensor_data = buffers[0] |
|||
print(f" INFO: Extracted tensor from single buffer of ScriptModule: {filepath}") |
|||
else: |
|||
raise ValueError(f"ScriptModule at {filepath} doesn't have .attr('tensor') and not single param/buffer.") |
|||
|
|||
if not isinstance(tensor_data, torch.Tensor): |
|||
raise TypeError(f"Loaded data from {filepath} is not a tensor (type: {type(tensor_data)})") |
|||
|
|||
if tensor_data.shape != param_tensor_template.data.shape: |
|||
print(f" WARNING: Shape mismatch for param {name}. Expected {param_tensor_template.data.shape}, got {tensor_data.shape} from {filepath}. Skipping.") |
|||
missed_params.append(name) |
|||
continue |
|||
new_state_dict[name] = tensor_data |
|||
loaded_count += 1 |
|||
except Exception as e: |
|||
print(f" ERROR loading or processing {filepath} for param {name}: {e}. Skipping.") |
|||
missed_params.append(name) |
|||
else: |
|||
# print(f" File not found for parameter {name}: {filepath}. Will be missed.") |
|||
missed_params.append(name) |
|||
|
|||
# Buffers |
|||
for name, buffer_tensor_template in model_to_populate.named_buffers(): |
|||
expected_filename = convert_param_name_to_filename(name) |
|||
filepath = os.path.join(source_dir, expected_filename) |
|||
if os.path.exists(filepath): |
|||
try: |
|||
# print(f" Loading buffer: {name} from {filepath}") |
|||
tensor_data = torch.load(filepath, map_location=torch.device('cpu')) |
|||
|
|||
if isinstance(tensor_data, torch.jit.ScriptModule): |
|||
try: |
|||
tensor_data = tensor_data.attr("tensor").toTensor() |
|||
print(f" INFO: Extracted tensor via .attr('tensor') from ScriptModule: {filepath}") |
|||
except RuntimeError: |
|||
params = list(tensor_data.parameters()) |
|||
buffers = list(tensor_data.buffers()) |
|||
if len(buffers) == 1 and not params: |
|||
tensor_data = buffers[0] |
|||
print(f" INFO: Extracted tensor from single buffer of ScriptModule: {filepath}") |
|||
elif len(params) == 1 and not buffers: |
|||
tensor_data = params[0] |
|||
print(f" INFO: Extracted tensor from single param of ScriptModule: {filepath}") |
|||
else: |
|||
raise ValueError(f"ScriptModule at {filepath} doesn't have .attr('tensor') and not single param/buffer.") |
|||
|
|||
if not isinstance(tensor_data, torch.Tensor): |
|||
raise TypeError(f"Loaded data from {filepath} is not a tensor (type: {type(tensor_data)})") |
|||
|
|||
if tensor_data.shape != buffer_tensor_template.data.shape: |
|||
print(f" WARNING: Shape mismatch for buffer {name}. Expected {buffer_tensor_template.data.shape}, got {tensor_data.shape} from {filepath}. Skipping.") |
|||
missed_buffers.append(name) |
|||
continue |
|||
new_state_dict[name] = tensor_data |
|||
loaded_count += 1 |
|||
except Exception as e: |
|||
print(f" ERROR loading or processing {filepath} for buffer {name}: {e}. Skipping.") |
|||
missed_buffers.append(name) |
|||
else: |
|||
# print(f" File not found for buffer {name}: {filepath}. Will be missed.") |
|||
missed_buffers.append(name) |
|||
|
|||
if loaded_count > 0: |
|||
print(f"Attempting to load {loaded_count} found tensors into model state_dict.") |
|||
result = model_to_populate.load_state_dict(new_state_dict, strict=False) |
|||
print("State_dict loading result:") |
|||
if result.missing_keys: |
|||
print(f" Strict load missing_keys ({len(result.missing_keys)}): {result.missing_keys[:20]}...") # Print first 20 |
|||
if result.unexpected_keys: |
|||
print(f" Strict load unexpected_keys ({len(result.unexpected_keys)}): {result.unexpected_keys[:20]}...") |
|||
|
|||
# Cross check with our own missed lists |
|||
print(f"Manually tracked missed parameters ({len(missed_params)}): {missed_params[:20]}...") |
|||
print(f"Manually tracked missed buffers ({len(missed_buffers)}): {missed_buffers[:20]}...") |
|||
|
|||
# Check if all expected params/buffers in the model were loaded |
|||
all_model_keys = set(model_to_populate.state_dict().keys()) |
|||
loaded_keys = set(new_state_dict.keys()) |
|||
truly_missing_from_model = all_model_keys - loaded_keys |
|||
if truly_missing_from_model: |
|||
print(f"CRITICAL: Keys in model NOT found in source_dir ({len(truly_missing_from_model)}): {list(truly_missing_from_model)[:20]}...") |
|||
|
|||
if not truly_missing_from_model and not result.unexpected_keys : |
|||
print("Successfully loaded weights from individual files into the model.") |
|||
else: |
|||
print("WARNING: Some weights might be missing or unexpected after loading from individual files.") |
|||
if not loaded_keys: # if we loaded nothing |
|||
print("ERROR: No weights were successfully loaded from individual files. Aborting.") |
|||
sys.exit(1) |
|||
|
|||
|
|||
else: |
|||
print("ERROR: No weights were found or loaded from individual files. Aborting.") |
|||
sys.exit(1) |
|||
|
|||
def export_jit_wrapped_tensors(model, output_dir): |
|||
TENSOR_KEY_IN_CONTAINER = "tensor" # The key used in TensorContainer and for C++ loading |
|||
if not os.path.exists(output_dir): |
|||
os.makedirs(output_dir); print(f"Created output directory: {output_dir}") |
|||
|
|||
for name, param in model.named_parameters(): |
|||
filename = name + '.pt' |
|||
filepath = os.path.join(output_dir, filename) |
|||
print(f"Exporting JIT-wrapped parameter: {name} (as {filename}) to {filepath} with shape {param.data.shape}") |
|||
container = TensorContainer(param.data.clone().detach().cpu(), TENSOR_KEY_IN_CONTAINER) |
|||
scripted_container = torch.jit.script(container) |
|||
torch.jit.save(scripted_container, filepath) |
|||
|
|||
for name, buf in model.named_buffers(): |
|||
filename = name + '.pt' |
|||
filepath = os.path.join(output_dir, filename) |
|||
print(f"Exporting JIT-wrapped buffer: {name} (as {filename}) to {filepath} with shape {buf.data.shape}") |
|||
container = TensorContainer(buf.data.clone().detach().cpu(), TENSOR_KEY_IN_CONTAINER) |
|||
scripted_container = torch.jit.script(container) |
|||
torch.jit.save(scripted_container, filepath) |
|||
|
|||
print(f"All params/buffers exported as JIT-wrapped tensors to {output_dir} (using dot naming, key '{TENSOR_KEY_IN_CONTAINER}').") |
|||
|
|||
if __name__ == "__main__": |
|||
parser = argparse.ArgumentParser(description="Load ResNet-50 weights from a directory of individual underscore_named .pt files, then re-export them as JIT-wrapped (TensorContainer) dot_named .pt files for C++ loading.") |
|||
parser.add_argument('--source_individual_weights_dir', type=str, required=True, |
|||
help="Directory containing the source underscore_named .pt files (e.g., 'exported_weights/backbone/').") |
|||
parser.add_argument('--output_jit_wrapped_tensors_dir', type=str, required=True, |
|||
help="Directory to save the re-exported JIT-wrapped dot_named .pt files (e.g., 'exported_weights/raw_backbone/').") |
|||
|
|||
args = parser.parse_args() |
|||
|
|||
print("Instantiating a new ResNet-50 model (will be populated from source dir)...") |
|||
model = resnet50(output_layers=['layer4'], pretrained=False) |
|||
print("ResNet-50 model instantiated.") |
|||
|
|||
load_weights_from_individual_files(model, args.source_individual_weights_dir) |
|||
|
|||
export_jit_wrapped_tensors(model, args.output_jit_wrapped_tensors_dir) |
|||
|
|||
print("Process complete. Weights loaded from source (underscore_named) and re-exported as JIT-wrapped tensors (dot_named).") |
Some files were not shown because too many files changed in this diff
Write
Preview
Loading…
Cancel
Save
Reference in new issue