mirror of
				https://github.com/pytorch/pytorch.git
				synced 2025-10-27 17:54:55 +08:00 
			
		
		
		
	Compare commits
	
		
			79 Commits
		
	
	
		
			msaroufim/
			...
			v1.6.0-rc4
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 7c7c9c3aa6 | |||
| a2922f589d | |||
| 8acfecaecb | |||
| 860e18a61b | |||
| 8f804baaa9 | |||
| a395e0903e | |||
| 2ca55430d2 | |||
| b8e77a42bd | |||
| 4081fdd3df | |||
| cefb9e0cd6 | |||
| d9e9e0087a | |||
| 43d746305c | |||
| 9409e03903 | |||
| c9a1853d2f | |||
| 7fa9b2923b | |||
| 40bf15a8ac | |||
| c164fc4d7f | |||
| e0b7480f34 | |||
| 89d7f194d8 | |||
| 59bb44a8e8 | |||
| 8f4d01d9f1 | |||
| 77ffb25925 | |||
| af9600b1f5 | |||
| 83262b1ba1 | |||
| f862a6ba4d | |||
| f3c1ea7455 | |||
| 2ed3ad2891 | |||
| a857af50a4 | |||
| d0045e5520 | |||
| 0406b69b79 | |||
| 6220cc4380 | |||
| eaf3f2fd34 | |||
| c35b4c770b | |||
| 11baccf1b5 | |||
| f0f0cbdd4a | |||
| 11b70b0041 | |||
| 01e9562313 | |||
| 3f13c9a2c8 | |||
| 63a94c021a | |||
| 2b175ba909 | |||
| 8c3f662224 | |||
| 0ffdd5aa1d | |||
| d53427c541 | |||
| b44b1d868e | |||
| 9184c9832e | |||
| e89c4f0dec | |||
| ea273c68f9 | |||
| 4dd37bfbf7 | |||
| 2533b9da83 | |||
| c5c8a85a82 | |||
| b4b8f5b9d4 | |||
| 41816dc97f | |||
| 31d9776c04 | |||
| ddea6c552f | |||
| 091537a764 | |||
| bf4d905ea1 | |||
| 415e499330 | |||
| eaf7dad5d6 | |||
| 75a074abdc | |||
| dede34eab7 | |||
| 0c90b6da5c | |||
| 4316199832 | |||
| f993e5ac88 | |||
| c5bd737f0c | |||
| fe45c2c986 | |||
| a9996bb482 | |||
| bdfcbfa18c | |||
| ea1b0dba18 | |||
| 6d85b2c989 | |||
| 44f79651a7 | |||
| 8682ac147b | |||
| 4cc605e80a | |||
| b0cce716f7 | |||
| 0dc93ac119 | |||
| bb848df10b | |||
| 2dc0b84aca | |||
| 168cddf5f1 | |||
| bc8760b3db | |||
| 4269b9a8fc | 
| @ -36,6 +36,12 @@ CONFIG_TREE_DATA = [ | ||||
|                     ("libtorch", [XImportant(True)]) | ||||
|                 ]), | ||||
|             ]), | ||||
|             ("11.0", [ | ||||
|                 X("3.8"), | ||||
|                 ("3.8", [ | ||||
|                     ("libtorch", [X(True)]) | ||||
|                 ]), | ||||
|             ]), | ||||
|         ]), | ||||
|     ]), | ||||
|     ("bionic", [ | ||||
|  | ||||
| @ -49,7 +49,8 @@ class Conf: | ||||
|  | ||||
|         cuda_parms = [] | ||||
|         if self.cuda_version: | ||||
|             cuda_parms.extend(["cuda" + self.cuda_version, "cudnn7"]) | ||||
|             cudnn = "cudnn8" if self.cuda_version.startswith("11.") else "cudnn7" | ||||
|             cuda_parms.extend(["cuda" + self.cuda_version, cudnn]) | ||||
|         result = leading + ["linux", self.distro] + cuda_parms + self.parms | ||||
|         if not for_docker and self.parms_list_ignored_for_docker_image is not None: | ||||
|             result = result + self.parms_list_ignored_for_docker_image | ||||
| @ -222,8 +223,7 @@ def instantiate_configs(): | ||||
|                 python_version = fc.find_prop("pyver") | ||||
|                 parms_list[0] = fc.find_prop("abbreviated_pyver") | ||||
|  | ||||
|         if cuda_version in ["9.2", "10", "10.1", "10.2"]: | ||||
|             # TODO The gcc version is orthogonal to CUDA version? | ||||
|         if cuda_version: | ||||
|             cuda_gcc_version = fc.find_prop("cuda_gcc_override") or "gcc7" | ||||
|             parms_list.append(cuda_gcc_version) | ||||
|  | ||||
|  | ||||
| @ -958,6 +958,11 @@ jobs: | ||||
|         no_output_timeout: "1h" | ||||
|         command: | | ||||
|             source "/pytorch/.circleci/scripts/binary_linux_build.sh" | ||||
|     - run: | ||||
|         name: Output binary sizes | ||||
|         no_output_timeout: "1m" | ||||
|         command: | | ||||
|             ls -lah /final_pkgs | ||||
|     - run: | ||||
|         name: save binary size | ||||
|         no_output_timeout: "5m" | ||||
| @ -972,6 +977,9 @@ jobs: | ||||
|         root: / | ||||
|         paths: final_pkgs | ||||
|  | ||||
|     - store_artifacts: | ||||
|         path: /final_pkgs | ||||
|  | ||||
|     # This should really just be another step of the binary_linux_build job above. | ||||
|     # This isn't possible right now b/c the build job uses the docker executor | ||||
|     # (otherwise they'd be really really slow) but this one uses the macine | ||||
| @ -7388,6 +7396,54 @@ workflows: | ||||
|           docker_image: "308535385114.dkr.ecr.us-east-1.amazonaws.com/pytorch/pytorch-linux-xenial-cuda10.2-cudnn7-py3-gcc7:209062ef-ab58-422a-b295-36c4eed6e906" | ||||
|           use_cuda_docker_runtime: "1" | ||||
|           resource_class: gpu.medium | ||||
|       - pytorch_linux_build: | ||||
|           name: pytorch_linux_xenial_cuda11_0_cudnn8_py3_gcc7_build | ||||
|           filters: | ||||
|             branches: | ||||
|               only: | ||||
|                 - master | ||||
|                 - /ci-all\/.*/ | ||||
|                 - /release\/.*/ | ||||
|           build_environment: "pytorch-linux-xenial-cuda11.0-cudnn8-py3-gcc7-build" | ||||
|           docker_image: "308535385114.dkr.ecr.us-east-1.amazonaws.com/pytorch/pytorch-linux-xenial-cuda11.0-cudnn8-py3-gcc7:209062ef-ab58-422a-b295-36c4eed6e906" | ||||
|       - pytorch_linux_test: | ||||
|           name: pytorch_linux_xenial_cuda11_0_cudnn8_py3_gcc7_test | ||||
|           requires: | ||||
|             - pytorch_linux_xenial_cuda11_0_cudnn8_py3_gcc7_build | ||||
|           filters: | ||||
|             branches: | ||||
|               only: | ||||
|                 - master | ||||
|                 - /ci-all\/.*/ | ||||
|                 - /release\/.*/ | ||||
|           build_environment: "pytorch-linux-xenial-cuda11.0-cudnn8-py3-gcc7-test" | ||||
|           docker_image: "308535385114.dkr.ecr.us-east-1.amazonaws.com/pytorch/pytorch-linux-xenial-cuda11.0-cudnn8-py3-gcc7:209062ef-ab58-422a-b295-36c4eed6e906" | ||||
|           use_cuda_docker_runtime: "1" | ||||
|           resource_class: gpu.medium | ||||
|       - pytorch_linux_build: | ||||
|           name: pytorch_libtorch_linux_xenial_cuda11_0_cudnn8_py3_gcc7_build | ||||
|           filters: | ||||
|             branches: | ||||
|               only: | ||||
|                 - master | ||||
|                 - /ci-all\/.*/ | ||||
|                 - /release\/.*/ | ||||
|           build_environment: "pytorch-libtorch-linux-xenial-cuda11.0-cudnn8-py3-gcc7-build" | ||||
|           docker_image: "308535385114.dkr.ecr.us-east-1.amazonaws.com/pytorch/pytorch-linux-xenial-cuda11.0-cudnn8-py3-gcc7:209062ef-ab58-422a-b295-36c4eed6e906" | ||||
|       - pytorch_linux_test: | ||||
|           name: pytorch_libtorch_linux_xenial_cuda11_0_cudnn8_py3_gcc7_test | ||||
|           requires: | ||||
|             - pytorch_libtorch_linux_xenial_cuda11_0_cudnn8_py3_gcc7_build | ||||
|           filters: | ||||
|             branches: | ||||
|               only: | ||||
|                 - master | ||||
|                 - /ci-all\/.*/ | ||||
|                 - /release\/.*/ | ||||
|           build_environment: "pytorch-libtorch-linux-xenial-cuda11.0-cudnn8-py3-gcc7-test" | ||||
|           docker_image: "308535385114.dkr.ecr.us-east-1.amazonaws.com/pytorch/pytorch-linux-xenial-cuda11.0-cudnn8-py3-gcc7:209062ef-ab58-422a-b295-36c4eed6e906" | ||||
|           use_cuda_docker_runtime: "1" | ||||
|           resource_class: gpu.medium | ||||
|       - pytorch_linux_build: | ||||
|           name: pytorch_linux_bionic_py3_6_clang9_build | ||||
|           build_environment: "pytorch-linux-bionic-py3.6-clang9-build" | ||||
|  | ||||
| @ -14,7 +14,7 @@ mkdir -p ${ZIP_DIR}/src | ||||
| cp -R ${ARTIFACTS_DIR}/arm64/include ${ZIP_DIR}/install/ | ||||
| # build a FAT bianry | ||||
| cd ${ZIP_DIR}/install/lib | ||||
| target_libs=(libc10.a libclog.a libcpuinfo.a libeigen_blas.a libpytorch_qnnpack.a libtorch_cpu.a libtorch.a libXNNPACK.a) | ||||
| target_libs=(libc10.a libclog.a libcpuinfo.a libeigen_blas.a libpthreadpool.a libpytorch_qnnpack.a libtorch_cpu.a libtorch.a libXNNPACK.a) | ||||
| for lib in ${target_libs[*]} | ||||
| do | ||||
|     if [ -f "${ARTIFACTS_DIR}/x86_64/lib/${lib}" ] && [ -f "${ARTIFACTS_DIR}/arm64/lib/${lib}" ]; then | ||||
|  | ||||
| @ -20,6 +20,7 @@ PIP_UPLOAD_FOLDER=${PIP_UPLOAD_FOLDER:-nightly} | ||||
| CONDA_UPLOAD_CHANNEL=$(echo "${PIP_UPLOAD_FOLDER}" | sed 's:/*$::') | ||||
| BACKUP_BUCKET="s3://pytorch-backup" | ||||
|  | ||||
| retry pip install -q awscli | ||||
| # Upload the package to the final location | ||||
| pushd /home/circleci/project/final_pkgs | ||||
| if [[ "$PACKAGE_TYPE" == conda ]]; then | ||||
| @ -30,14 +31,12 @@ if [[ "$PACKAGE_TYPE" == conda ]]; then | ||||
|   subdir=$(tar -xOf ./*.bz2 info/index.json | grep subdir  | cut -d ':' -f2 | sed -e 's/[[:space:]]//' -e 's/"//g' -e 's/,//') | ||||
|   BACKUP_DIR="conda/${subdir}" | ||||
| elif [[ "$PACKAGE_TYPE" == libtorch ]]; then | ||||
|   retry pip install -q awscli | ||||
|   s3_dir="s3://pytorch/libtorch/${PIP_UPLOAD_FOLDER}${DESIRED_CUDA}/" | ||||
|   for pkg in $(ls); do | ||||
|     retry aws s3 cp "$pkg" "$s3_dir" --acl public-read | ||||
|   done | ||||
|   BACKUP_DIR="libtorch/${PIP_UPLOAD_FOLDER}${DESIRED_CUDA}/" | ||||
| else | ||||
|   retry pip install -q awscli | ||||
|   s3_dir="s3://pytorch/whl/${PIP_UPLOAD_FOLDER}${DESIRED_CUDA}/" | ||||
|   retry aws s3 cp "$(ls)" "$s3_dir" --acl public-read | ||||
|   BACKUP_DIR="whl/${PIP_UPLOAD_FOLDER}${DESIRED_CUDA}/" | ||||
| @ -45,5 +44,5 @@ fi | ||||
|  | ||||
| if [[ -n "${CIRCLE_TAG:-}" ]]; then | ||||
|   s3_dir="${BACKUP_BUCKET}/${CIRCLE_TAG}/${BACKUP_DIR}" | ||||
|   retry aws s3 cp . "$s3_dir" | ||||
|   retry aws s3 cp --recursive . "$s3_dir" | ||||
| fi | ||||
|  | ||||
| @ -21,6 +21,7 @@ PIP_UPLOAD_FOLDER=${PIP_UPLOAD_FOLDER:-nightly} | ||||
| CONDA_UPLOAD_CHANNEL=$(echo "${PIP_UPLOAD_FOLDER}" | sed 's:/*$::') | ||||
| BACKUP_BUCKET="s3://pytorch-backup" | ||||
|  | ||||
| retry pip install -q awscli | ||||
| pushd "$workdir/final_pkgs" | ||||
| if [[ "$PACKAGE_TYPE" == conda ]]; then | ||||
|   retry conda install -yq anaconda-client | ||||
| @ -30,14 +31,12 @@ if [[ "$PACKAGE_TYPE" == conda ]]; then | ||||
|   subdir=$(tar -xOf ./*.bz2 info/index.json | grep subdir  | cut -d ':' -f2 | sed -e 's/[[:space:]]//' -e 's/"//g' -e 's/,//') | ||||
|   BACKUP_DIR="conda/${subdir}" | ||||
| elif [[ "$PACKAGE_TYPE" == libtorch ]]; then | ||||
|   retry pip install -q awscli | ||||
|   s3_dir="s3://pytorch/libtorch/${PIP_UPLOAD_FOLDER}${DESIRED_CUDA}/" | ||||
|   for pkg in $(ls); do | ||||
|     retry aws s3 cp "$pkg" "$s3_dir" --acl public-read | ||||
|   done | ||||
|   BACKUP_DIR="libtorch/${PIP_UPLOAD_FOLDER}${DESIRED_CUDA}/" | ||||
| else | ||||
|   retry pip install -q awscli | ||||
|   s3_dir="s3://pytorch/whl/${PIP_UPLOAD_FOLDER}${DESIRED_CUDA}/" | ||||
|   retry aws s3 cp "$(ls)" "$s3_dir" --acl public-read | ||||
|   BACKUP_DIR="whl/${PIP_UPLOAD_FOLDER}${DESIRED_CUDA}/" | ||||
| @ -45,5 +44,5 @@ fi | ||||
|  | ||||
| if [[ -n "${CIRCLE_TAG:-}" ]]; then | ||||
|   s3_dir="${BACKUP_BUCKET}/${CIRCLE_TAG}/${BACKUP_DIR}" | ||||
|   retry aws s3 cp . "$s3_dir" | ||||
|   retry aws s3 cp --recursive . "$s3_dir" | ||||
| fi | ||||
|  | ||||
| @ -19,6 +19,7 @@ PIP_UPLOAD_FOLDER=${PIP_UPLOAD_FOLDER:-nightly/} | ||||
| CONDA_UPLOAD_CHANNEL=$(echo "${PIP_UPLOAD_FOLDER}" | sed 's:/*$::') | ||||
| BACKUP_BUCKET="s3://pytorch-backup" | ||||
|  | ||||
| retry pip install -q awscli | ||||
| pushd /root/workspace/final_pkgs | ||||
| # Upload the package to the final location | ||||
| if [[ "$PACKAGE_TYPE" == conda ]]; then | ||||
| @ -29,14 +30,12 @@ if [[ "$PACKAGE_TYPE" == conda ]]; then | ||||
|   subdir=$(tar -xOf ./*.bz2 info/index.json | grep subdir  | cut -d ':' -f2 | sed -e 's/[[:space:]]//' -e 's/"//g' -e 's/,//') | ||||
|   BACKUP_DIR="conda/${subdir}" | ||||
| elif [[ "$PACKAGE_TYPE" == libtorch ]]; then | ||||
|   retry conda install -c conda-forge -yq awscli | ||||
|   s3_dir="s3://pytorch/libtorch/${PIP_UPLOAD_FOLDER}${DESIRED_CUDA}/" | ||||
|   for pkg in $(ls); do | ||||
|     retry aws s3 cp "$pkg" "$s3_dir" --acl public-read | ||||
|   done | ||||
|   BACKUP_DIR="libtorch/${PIP_UPLOAD_FOLDER}${DESIRED_CUDA}/" | ||||
| else | ||||
|   retry conda install -c conda-forge -yq awscli | ||||
|   s3_dir="s3://pytorch/whl/${PIP_UPLOAD_FOLDER}${DESIRED_CUDA}/" | ||||
|   retry aws s3 cp "$(ls)" "$s3_dir" --acl public-read | ||||
|   BACKUP_DIR="whl/${PIP_UPLOAD_FOLDER}${DESIRED_CUDA}/" | ||||
| @ -44,5 +43,5 @@ fi | ||||
|  | ||||
| if [[ -n "${CIRCLE_TAG:-}" ]]; then | ||||
|   s3_dir="${BACKUP_BUCKET}/${CIRCLE_TAG}/${BACKUP_DIR}" | ||||
|   retry aws s3 cp . "$s3_dir" | ||||
|   retry aws s3 cp --recursive . "$s3_dir" | ||||
| fi | ||||
|  | ||||
| @ -41,6 +41,11 @@ | ||||
|         no_output_timeout: "1h" | ||||
|         command: | | ||||
|             source "/pytorch/.circleci/scripts/binary_linux_build.sh" | ||||
|     - run: | ||||
|         name: Output binary sizes | ||||
|         no_output_timeout: "1m" | ||||
|         command: | | ||||
|             ls -lah /final_pkgs | ||||
|     - run: | ||||
|         name: save binary size | ||||
|         no_output_timeout: "5m" | ||||
| @ -55,6 +60,9 @@ | ||||
|         root: / | ||||
|         paths: final_pkgs | ||||
|  | ||||
|     - store_artifacts: | ||||
|         path: /final_pkgs | ||||
|  | ||||
|     # This should really just be another step of the binary_linux_build job above. | ||||
|     # This isn't possible right now b/c the build job uses the docker executor | ||||
|     # (otherwise they'd be really really slow) but this one uses the macine | ||||
|  | ||||
| @ -181,7 +181,7 @@ fi | ||||
|  | ||||
| # Patch required to build xla | ||||
| if [[ "${BUILD_ENVIRONMENT}" == *xla* ]]; then | ||||
|   git clone --recursive https://github.com/pytorch/xla.git | ||||
|   git clone --recursive -b r1.6 https://github.com/pytorch/xla.git | ||||
|   ./xla/scripts/apply_patches.sh | ||||
| fi | ||||
|  | ||||
|  | ||||
| @ -185,9 +185,9 @@ function get_exit_code() { | ||||
| function file_diff_from_base() { | ||||
|   # The fetch may fail on Docker hosts, but it's not always necessary. | ||||
|   set +e | ||||
|   git fetch origin master --quiet | ||||
|   git fetch origin release/1.6 --quiet | ||||
|   set -e | ||||
|   git diff --name-only "$(git merge-base origin/master HEAD)" > "$1" | ||||
|   git diff --name-only "$(git merge-base origin/release/1.6 HEAD)" > "$1" | ||||
| } | ||||
|  | ||||
| function get_bazel() { | ||||
|  | ||||
| @ -289,7 +289,7 @@ test_backward_compatibility() { | ||||
|   pushd test/backward_compatibility | ||||
|   python dump_all_function_schemas.py --filename new_schemas.txt | ||||
|   pip_uninstall torch | ||||
|   pip_install --pre torch -f https://download.pytorch.org/whl/nightly/cpu/torch_nightly.html | ||||
|   pip_install --pre torch -f https://download.pytorch.org/whl/test/cpu/torch_test.html | ||||
|   python check_backward_compatibility.py --new-schemas new_schemas.txt | ||||
|   popd | ||||
|   set +x | ||||
| @ -341,8 +341,8 @@ elif [[ "${BUILD_ENVIRONMENT}" == *-test2 || "${JOB_BASE_NAME}" == *-test2 ]]; t | ||||
| elif [[ "${BUILD_ENVIRONMENT}" == *-bazel-* ]]; then | ||||
|   test_bazel | ||||
| elif [[ "${BUILD_ENVIRONMENT}" == pytorch-linux-xenial-cuda9.2-cudnn7-py3-gcc5.4* ]]; then | ||||
|   # test cpp extension for xenial + cuda 9.2 + gcc 5.4 to make sure  | ||||
|   # cpp extension can be built correctly under this old env  | ||||
|   # test cpp extension for xenial + cuda 9.2 + gcc 5.4 to make sure | ||||
|   # cpp extension can be built correctly under this old env | ||||
|   test_cpp_extensions | ||||
| else | ||||
|   test_torchvision | ||||
|  | ||||
| @ -1350,7 +1350,6 @@ filegroup( | ||||
|         "caffe2/utils/smart_tensor_printer.cc", | ||||
|         "caffe2/utils/string_utils.cc", | ||||
|         "caffe2/utils/threadpool/ThreadPool.cc", | ||||
|         "caffe2/utils/threadpool/ThreadPoolMobile.cc", | ||||
|         "caffe2/utils/threadpool/pthreadpool.cc", | ||||
|         "caffe2/utils/threadpool/pthreadpool_impl.cc", | ||||
|     ], | ||||
|  | ||||
| @ -481,7 +481,7 @@ if(USE_PYTORCH_QNNPACK) | ||||
| endif() | ||||
|  | ||||
| if(USE_XNNPACK) | ||||
|   set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DUSE_XNNPACK -DUSE_INTERNAL_THREADPOOL_IMPL") | ||||
|   set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DUSE_XNNPACK") | ||||
| endif() | ||||
|  | ||||
| if(USE_VULKAN) | ||||
|  | ||||
| @ -99,6 +99,7 @@ if(ANDROID_ABI) | ||||
|   import_static_lib(libnnpack) | ||||
|   import_static_lib(libXNNPACK) | ||||
|   import_static_lib(libpytorch_qnnpack) | ||||
|   import_static_lib(libpthreadpool) | ||||
|   import_static_lib(libeigen_blas) | ||||
|   import_static_lib(libcpuinfo) | ||||
|   import_static_lib(libclog) | ||||
| @ -115,6 +116,7 @@ if(ANDROID_ABI) | ||||
|       libnnpack | ||||
|       libXNNPACK | ||||
|       libpytorch_qnnpack | ||||
|       libpthreadpool | ||||
|       libeigen_blas | ||||
|       libcpuinfo | ||||
|       libclog | ||||
| @ -129,6 +131,7 @@ else() | ||||
|       nnpack | ||||
|       XNNPACK | ||||
|       pytorch_qnnpack | ||||
|       pthreadpool | ||||
|       cpuinfo | ||||
|       clog | ||||
|   ) | ||||
|  | ||||
| @ -8,8 +8,10 @@ | ||||
|  | ||||
| #include "pytorch_jni_common.h" | ||||
| #if defined(__ANDROID__) | ||||
| #include <caffe2/utils/threadpool/ThreadPool.h> | ||||
| #include <caffe2/utils/threadpool/ThreadPoolMobile.h> | ||||
| #ifndef USE_PTHREADPOOL | ||||
| #define USE_PTHREADPOOL | ||||
| #endif /* USE_PTHREADPOOL */ | ||||
| #include <caffe2/utils/threadpool/pthreadpool-cpp.h> | ||||
| #endif | ||||
|  | ||||
| namespace pytorch_jni { | ||||
| @ -605,7 +607,7 @@ class PyTorchAndroidJni : public facebook::jni::JavaClass<PyTorchAndroidJni> { | ||||
|   } | ||||
|  | ||||
|   static void setNumThreads(facebook::jni::alias_ref<jclass>, jint numThreads) { | ||||
|     caffe2::mobile_threadpool()->setNumThreads(numThreads); | ||||
|     caffe2::pthreadpool()->set_thread_count(numThreads); | ||||
|   } | ||||
| }; | ||||
| #endif | ||||
|  | ||||
| @ -56,6 +56,38 @@ | ||||
|     - THBoolTensor* mask | ||||
|     - THTensor* source | ||||
| ]] | ||||
| [[ | ||||
|   name: _th_masked_select | ||||
|   cname: maskedSelect | ||||
|   cpu_bool: True | ||||
|   cpu_bfloat16: True | ||||
|   variants: | ||||
|     - function | ||||
|   backends: | ||||
|     - CPU | ||||
|   return: argument 0 | ||||
|   arguments: | ||||
|     - arg: THTensor* result | ||||
|       output: True | ||||
|     - THTensor* self | ||||
|     - THByteTensor* mask | ||||
| ]] | ||||
| [[ | ||||
|   name: _th_masked_select_bool | ||||
|   cname: maskedSelectBool | ||||
|   cpu_bool: True | ||||
|   cpu_bfloat16: True | ||||
|   variants: | ||||
|     - function | ||||
|   backends: | ||||
|     - CPU | ||||
|   return: argument 0 | ||||
|   arguments: | ||||
|     - arg: THTensor* result | ||||
|       output: True | ||||
|     - THTensor* self | ||||
|     - THBoolTensor* mask | ||||
| ]] | ||||
| [[ | ||||
|   name: _th_nonzero | ||||
|   cname: nonzero | ||||
|  | ||||
| @ -6,8 +6,7 @@ | ||||
| #ifndef C10_MOBILE | ||||
| #include <c10/core/thread_pool.h> | ||||
| #else | ||||
| #include <caffe2/utils/threadpool/ThreadPool.h> | ||||
| #include <caffe2/utils/threadpool/ThreadPoolMobile.h> | ||||
| #include <caffe2/utils/threadpool/pthreadpool-cpp.h> | ||||
| #endif // C10_MOBILE | ||||
|  | ||||
| #include <atomic> | ||||
| @ -88,15 +87,15 @@ void _run_with_pool(const std::function<void(int, size_t)>& fn, size_t range) { | ||||
|   // Run the first task on the current thread directly. | ||||
|   fn(0, 0); | ||||
| #else | ||||
|   caffe2::ThreadPool* pool = caffe2::mobile_threadpool(); | ||||
|   if (pool) { | ||||
|     // caffe2::ThreadPool can utilize the current thread. | ||||
|     pool->run(fn, range); | ||||
|   } else { | ||||
|     for (size_t i = 0; i < range; ++i) { | ||||
|       fn(0, i); | ||||
|     } | ||||
|   } | ||||
|   caffe2::PThreadPool* const pool = caffe2::pthreadpool(); | ||||
|   TORCH_INTERNAL_ASSERT(pool, "Invalid thread pool!"); | ||||
|  | ||||
|   pool->run( | ||||
|     // PThreadPool::run() is blocking.  A std::function [const] reference to | ||||
|     // this lambda cannot go out of scope before PThreadPool::run() returns. | ||||
|     [&fn](const size_t task_id) { | ||||
|       fn(0 /* unused */, task_id); | ||||
|     }, range); | ||||
| #endif // C10_MOBILE | ||||
| } | ||||
|  | ||||
| @ -184,7 +183,7 @@ void init_num_threads() { | ||||
| #endif | ||||
|  | ||||
| #ifdef C10_MOBILE | ||||
|   caffe2::mobile_threadpool(); | ||||
|   caffe2::pthreadpool(); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| @ -208,7 +207,9 @@ void set_num_threads(int nthreads) { | ||||
|     } | ||||
|   } | ||||
| #else | ||||
|   TORCH_CHECK(false, "set_num_threads is not supported for mobile."); | ||||
|   caffe2::PThreadPool* const pool = caffe2::pthreadpool(); | ||||
|   TORCH_INTERNAL_ASSERT(pool, "Invalid thread pool!"); | ||||
|   pool->set_thread_count(nthreads); | ||||
| #endif // C10_MOBILE | ||||
| } | ||||
|  | ||||
| @ -226,9 +227,9 @@ int get_num_threads() { | ||||
|     return _get_intraop_pool().size() + 1; | ||||
|   } | ||||
| #else | ||||
|   caffe2::ThreadPool* pool = caffe2::mobile_threadpool(); | ||||
|   // caffe2::ThreadPool::getNumThreads() counts the current thread. | ||||
|   return !pool || in_parallel_region() ? 1 /* current thread */ : pool->getNumThreads(); | ||||
|   caffe2::PThreadPool* const pool = caffe2::pthreadpool(); | ||||
|   TORCH_INTERNAL_ASSERT(pool, "Invalid thread pool!") | ||||
|   return in_parallel_region() ? 1 /* current thread */ : pool->get_thread_count(); | ||||
| #endif // C10_MOBILE | ||||
| } | ||||
|  | ||||
| @ -257,8 +258,8 @@ void intraop_launch(std::function<void()> func) { | ||||
|     func(); | ||||
|   } | ||||
| #else | ||||
|   // TODO: caffe2::ThreadPool doesn't support submitting tasks separately and | ||||
|   // running in parallel. Should fix it when this API becomes popular. | ||||
|   // TODO: caffe2::PThreadPool only provides a data-parallel API. | ||||
|   // Task parallelism is not currently supported. | ||||
|   func(); | ||||
| #endif // C10_MOBILE | ||||
| } | ||||
| @ -280,8 +281,8 @@ std::shared_ptr<c10::ivalue::Future> intraop_launch_future( | ||||
|   } | ||||
|   return future; | ||||
| #else | ||||
|   // TODO: caffe2::ThreadPool doesn't support submitting tasks separately and | ||||
|   // running in parallel. Should fix it when this API becomes popular. | ||||
|   // TODO: caffe2::PThreadPool only provides a data-parallel API. | ||||
|   // Task parallelism is not currently supported. | ||||
|   auto future = std::make_shared<c10::ivalue::Future>(NoneType::get()); | ||||
|   func(); | ||||
|   future->markCompleted(); | ||||
|  | ||||
| @ -135,6 +135,7 @@ UPTOb( bool  , equal    , (const Tensor &A, const Tensor &B) ) | ||||
| UPTOb( Tensor, cat      , (TensorList    A, int64_t       B) ) | ||||
| UPTOb( Tensor, cat      , (TensorList    A, Dimname       B) ) | ||||
| UPTOb( Tensor, _cat     , (TensorList    A, int64_t       B) ) | ||||
| UPTOd( Tensor, index_put, (const Tensor &A, TensorList    B, const Tensor &         C, bool          D) ) | ||||
| UPTOb( Tensor, stack    , (TensorList    A, int64_t       B) ) | ||||
|  | ||||
| #undef UPTOa | ||||
|  | ||||
| @ -482,15 +482,16 @@ TORCH_LIBRARY_IMPL(aten, Autocast, m) { | ||||
|   KERNEL(ADD_NS(addcdiv), "addcdiv", Tensor (const Tensor &, const Tensor &, const Tensor &, Scalar), promote) | ||||
|   KERNEL(ADD_NS(addcmul), "addcmul", Tensor (const Tensor &, const Tensor &, const Tensor &, Scalar), promote) | ||||
|   KERNEL(ADD_NS(atan2), "atan2", Tensor (const Tensor &, const Tensor &), promote) | ||||
|   KERNEL(ADD_NS(cross), "cross", Tensor (const Tensor &, const Tensor &, c10::optional<int64_t>), promote) | ||||
|   KERNEL_UNBOXED_ONLY(ADD_NS(bilinear), "bilinear", Tensor (const Tensor &, const Tensor &, const Tensor &, const Tensor &), promote) | ||||
|   KERNEL_UNBOXED_ONLY(ADD_NS(tensordot), "tensordot", Tensor (const Tensor &, const Tensor &, IntArrayRef, IntArrayRef), promote) | ||||
|   KERNEL_UNBOXED_ONLY(ADD_NS(dot), "dot", Tensor (const Tensor &, const Tensor &), promote) | ||||
|   KERNEL(ADD_NS(equal), "equal", bool (const Tensor &, const Tensor &), promote) | ||||
|   KERNEL(ADD_NS(cat), "cat", Tensor (TensorList, int64_t), promote) | ||||
|   KERNEL_UNBOXED_ONLY(ADD_NS(cat), "cat.names", Tensor (TensorList, Dimname), promote) | ||||
|   KERNEL(ADD_NS(_cat), "_cat", Tensor (TensorList, int64_t), promote) | ||||
|   KERNEL(ADD_NS(cross), "cross", Tensor (const Tensor &, const Tensor &, c10::optional<int64_t>), promote) | ||||
|   KERNEL_UNBOXED_ONLY(ADD_NS(dot), "dot", Tensor (const Tensor &, const Tensor &), promote) | ||||
|   KERNEL(ADD_NS(equal), "equal", bool (const Tensor &, const Tensor &), promote) | ||||
|   KERNEL_UNBOXED_ONLY(ADD_NS(index_put), "index_put", Tensor (const Tensor &, TensorList, const Tensor &, bool), promote) | ||||
|   KERNEL(ADD_NS(stack), "stack", Tensor (TensorList, int64_t), promote) | ||||
|   KERNEL_UNBOXED_ONLY(ADD_NS(tensordot), "tensordot", Tensor (const Tensor &, const Tensor &, IntArrayRef, IntArrayRef), promote) | ||||
|  | ||||
|   m.impl_UNBOXED("binary_cross_entropy", &at::autocast::binary_cross_entropy_banned); | ||||
| } | ||||
|  | ||||
| @ -188,6 +188,7 @@ namespace c10 { | ||||
|   _(prim, unchecked_unwrap_optional) \ | ||||
|   _(aten, __contains__)              \ | ||||
|   _(prim, BailoutTemplate)           \ | ||||
|   _(prim, grad)                      \ | ||||
|   _(aten, zero_)                     \ | ||||
|   _(aten, fill_)                     \ | ||||
|   FORALL_ATEN_BASE_SYMBOLS(_)        \ | ||||
|  | ||||
| @ -1481,7 +1481,7 @@ inline TypePtr TensorType::fromBoolType() { | ||||
|  | ||||
| inline c10::optional<c10::ScalarType> tryScalarTypeFromJitType(const c10::TypePtr & type) { | ||||
|   if (type == FloatType::get()) { | ||||
|     return at::ScalarType::Double; | ||||
|     return at::typeMetaToScalarType(c10::get_default_dtype()); | ||||
|   } else if (type == IntType::get()) { | ||||
|     return at::ScalarType::Long; | ||||
|   } else if (type == BoolType::get()) { | ||||
|  | ||||
| @ -181,6 +181,10 @@ Allocator* CUDAHooks::getPinnedMemoryAllocator() const { | ||||
|   return at::cuda::getPinnedMemoryAllocator(); | ||||
| } | ||||
|  | ||||
| Allocator* CUDAHooks::getCUDADeviceAllocator() const { | ||||
|   return at::cuda::getCUDADeviceAllocator(); | ||||
| } | ||||
|  | ||||
| bool CUDAHooks::compiledWithCuDNN() const { | ||||
|   return AT_CUDNN_ENABLED(); | ||||
| } | ||||
|  | ||||
| @ -22,6 +22,7 @@ struct CUDAHooks : public at::CUDAHooksInterface { | ||||
|   int64_t current_device() const override; | ||||
|   bool hasPrimaryContext(int64_t device_index) const override; | ||||
|   c10::optional<int64_t> getDevceIndexWithPrimaryContext() const override; | ||||
|   Allocator* getCUDADeviceAllocator() const override; | ||||
|   Allocator* getPinnedMemoryAllocator() const override; | ||||
|   bool compiledWithCuDNN() const override; | ||||
|   bool compiledWithMIOpen() const override; | ||||
|  | ||||
| @ -16,10 +16,15 @@ void destroyCuDNNHandle(cudnnHandle_t handle) { | ||||
| // happens in fbcode setting. @colesbury and I decided to not destroy | ||||
| // the handle as a workaround. | ||||
| //   - @soumith | ||||
| #ifdef NO_CUDNN_DESTROY_HANDLE | ||||
| #else | ||||
|     cudnnDestroy(handle); | ||||
| #endif | ||||
| // | ||||
| // Further note: this is now disabled globally, because we are seeing | ||||
| // the same issue as mentioned above in CUDA 11 CI. | ||||
| //   - @zasdfgbnm | ||||
| // | ||||
| // #ifdef NO_CUDNN_DESTROY_HANDLE | ||||
| // #else | ||||
| //   cudnnDestroy(handle); | ||||
| // #endif | ||||
| } | ||||
|  | ||||
| using CudnnPoolType = at::cuda::DeviceThreadHandlePool<cudnnHandle_t, createCuDNNHandle, destroyCuDNNHandle>; | ||||
|  | ||||
| @ -121,6 +121,10 @@ struct CAFFE2_API CUDAHooksInterface { | ||||
|     TORCH_CHECK(false, "Pinned memory requires CUDA. ", CUDA_HELP); | ||||
|   } | ||||
|  | ||||
|   virtual Allocator* getCUDADeviceAllocator() const { | ||||
|     TORCH_CHECK(false, "CUDADeviceAllocator requires CUDA. ", CUDA_HELP); | ||||
|   } | ||||
|  | ||||
|   virtual bool compiledWithCuDNN() const { | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
| @ -262,9 +262,7 @@ auto ConvParams::use_xnnpack( | ||||
|     const at::Tensor& input, | ||||
|     const at::Tensor& weight, | ||||
|     const at::Tensor& bias) const -> bool { | ||||
| // Disable the xnnpack operators for both iOS and macOS temporarily due to the crash in pthreadpool | ||||
| // TODO:T66297472 remove `!defined(__APPLE__)` once we figure out the root cause of the crash. | ||||
| #if defined(C10_MOBILE) && !defined(__APPLE__) | ||||
| #if defined(C10_MOBILE) | ||||
|   if (!transposed) { | ||||
|     return (input.size(1) == groups) && | ||||
|             xnnpack::use_convolution2d( | ||||
|  | ||||
| @ -22,6 +22,32 @@ Tensor & masked_scatter__cpu(Tensor& self, const Tensor & mask, const Tensor & s | ||||
|   } | ||||
| } | ||||
|  | ||||
| Tensor masked_select_cpu(const Tensor & self, const Tensor & mask) { | ||||
|   namedinference::compute_broadcast_outnames(self, mask); | ||||
|  | ||||
|   Tensor b_self, b_mask; | ||||
|   std::tie(b_self, b_mask) = expand_outplace(self, mask, "masked_select"); | ||||
|   if (b_mask.dtype() == at::ScalarType::Byte) { | ||||
|     TORCH_WARN("masked_select received a mask with dtype torch.uint8, this behavior is now deprecated," \ | ||||
|             "please use a mask with dtype torch.bool instead."); | ||||
|     return legacy::cpu::_th_masked_select(b_self, b_mask); | ||||
|   } else { | ||||
|     return legacy::cpu::_th_masked_select_bool(b_self, b_mask); | ||||
|   } | ||||
| } | ||||
|  | ||||
| Tensor & masked_select_out_cpu(Tensor & result, const Tensor & self, const Tensor & mask) { | ||||
|   namedinference::compute_broadcast_outnames(self, mask); | ||||
|  | ||||
|   Tensor b_self, b_mask; | ||||
|   std::tie(b_self, b_mask) = expand_outplace(self, mask, "masked_select_out"); | ||||
|   if (b_mask.dtype() == at::ScalarType::Bool) { | ||||
|     return legacy::cpu::_th_masked_select_bool_out(result, b_self, b_mask); | ||||
|   } else { | ||||
|     return legacy::cpu::_th_masked_select_out(result, b_self, b_mask); | ||||
|   } | ||||
| } | ||||
|  | ||||
| Tensor argsort(const Tensor & self, int64_t dim, bool descending) { | ||||
|   return std::get<1>(at::sort(self, dim, descending)); | ||||
| } | ||||
|  | ||||
| @ -17,9 +17,7 @@ Tensor linear(const Tensor& input, const Tensor& weight, const Tensor& bias) { | ||||
|   if (input.is_mkldnn()) { | ||||
|     return at::mkldnn_linear(input, weight, bias); | ||||
|   } | ||||
| // Disable the xnnpack operators for both iOS and macOS temporarily due to the crash in pthreadpool | ||||
| // TODO:T66297472 remove `!defined(__APPLE__)` once we figure out the root cause of the crash. | ||||
| #if defined(C10_MOBILE) && !defined(__APPLE__) | ||||
| #if defined(C10_MOBILE) | ||||
|   if (xnnpack::use_linear(input, weight, bias)) { | ||||
|     return xnnpack::linear(input, weight, bias); | ||||
|   } | ||||
|  | ||||
| @ -58,8 +58,9 @@ bool _nnpack_available() { | ||||
|  | ||||
| #include <nnpack.h> | ||||
|  | ||||
| #include <caffe2/utils/threadpool/ThreadPoolMobile.h> | ||||
| #include <caffe2/utils/threadpool/pthreadpool-cpp.h> | ||||
| #include <ATen/native/ConvUtils.h> | ||||
| #include <ATen/Parallel.h> | ||||
|  | ||||
| namespace at { | ||||
| namespace native { | ||||
| @ -87,15 +88,9 @@ static bool init_nnpack() { | ||||
| } | ||||
|  | ||||
| static pthreadpool_t nnpack_threadpool() { | ||||
|   // Try initializing a threadpool for NNPACK's use.  If we fail to | ||||
|   // successfully initialize an implementation, return nullptr which will | ||||
|   // instruct NNPACK to run single threaded. | ||||
|  | ||||
| #ifdef C10_MOBILE | ||||
|   // If building for mobile, use Caffe 2's mobile-friendly threadpool. | ||||
|   return caffe2::mobile_pthreadpool(); | ||||
|   return caffe2::pthreadpool_(); | ||||
| #else | ||||
|   // Otherwise, try using pthreadpool if we manage to initialize it successfully. | ||||
|   static pthreadpool_t nnpack_threadpool_ = nullptr; | ||||
|   static bool called_nnpack_threadpool_ = false; | ||||
|  | ||||
|  | ||||
| @ -135,9 +135,7 @@ Tensor max_pool2d( | ||||
|         self, kernel_size, stride, padding, dilation, ceil_mode); | ||||
|   } | ||||
|  | ||||
| // Disable the xnnpack operators for both iOS and macOS temporarily due to the crash in pthreadpool | ||||
| // TODO:T66297472 remove `!defined(__APPLE__)` once we figure out the root cause of the crash. | ||||
| #if defined(C10_MOBILE) && !defined(__APPLE__) | ||||
| #if defined(C10_MOBILE) | ||||
|   if(xnnpack::use_max_pool2d(self, kernel_size, padding, stride, | ||||
|                              dilation, ceil_mode)) { | ||||
|     return xnnpack::max_pool2d( | ||||
|  | ||||
| @ -34,12 +34,17 @@ static void scatter_gather_dtype_check( | ||||
| // Test: | ||||
| // 1. index.size(d) == self.size(d) for all d != dim | ||||
| // 2. index.size(d) <= src.size(d) for all d != dim | ||||
| // 3. index.dim() == self.dim() == src.dim() | ||||
| static void gather_shape_check(const Tensor& self, int64_t dim, | ||||
|   const Tensor& index, const Tensor& src | ||||
| ) { | ||||
|   auto self_dims = ensure_nonempty_dim(self.dim()); | ||||
|  | ||||
|   TORCH_CHECK(self_dims == ensure_nonempty_dim(index.dim()), | ||||
|     "Index tensor must have the same number of dimensions as out tensor" | ||||
|   ); | ||||
|  | ||||
|   auto src_dims = ensure_nonempty_dim(src.dim()); | ||||
|   TORCH_CHECK(src_dims == ensure_nonempty_dim(index.dim()), | ||||
|     "Index tensor must have the same number of dimensions as input tensor" | ||||
|   ); | ||||
|  | ||||
| @ -66,10 +71,16 @@ static void gather_shape_check(const Tensor& self, int64_t dim, | ||||
| // Tests: | ||||
| //  1. index.size(d) <= self.size(d) for all d != dim | ||||
| //  2. index.size(d) <= src.size(d) for all d if src is a Tensor | ||||
| //  3. index.dim() == self.dim() == src.dim() | ||||
| static void scatter_shape_check( | ||||
|   const Tensor& self, int64_t dim, const Tensor& index, | ||||
|   const c10::optional<Tensor>& src_opt = c10::nullopt | ||||
| ) { | ||||
|   TORCH_CHECK( | ||||
|     ensure_nonempty_dim(self.dim()) == ensure_nonempty_dim(index.dim()), | ||||
|     "Index tensor must have the same number of dimensions as self tensor" | ||||
|   ); | ||||
|  | ||||
|   bool is_wrong_shape = false; | ||||
|   int64_t self_dims = ensure_nonempty_dim(self.dim()); | ||||
|  | ||||
| @ -97,6 +108,12 @@ static void scatter_shape_check( | ||||
|  | ||||
|   if (src_opt.has_value()) { | ||||
|     auto src = src_opt.value(); | ||||
|  | ||||
|     TORCH_CHECK( | ||||
|       ensure_nonempty_dim(src.dim()) == ensure_nonempty_dim(index.dim()), | ||||
|       "Index tensor must have the same number of dimensions as src tensor" | ||||
|     ); | ||||
|  | ||||
|     TORCH_CHECK(!is_wrong_shape, | ||||
|       "Expected index ", index.sizes(), | ||||
|       " to be smaller than self ", self.sizes(), | ||||
|  | ||||
| @ -71,8 +71,6 @@ DEFINE_DISPATCH(index_put_stub); | ||||
| DEFINE_DISPATCH(index_put_accum_stub); | ||||
| DEFINE_DISPATCH(masked_fill_stub); | ||||
| REGISTER_NO_CPU_DISPATCH(index_put_accum_stub, index_put_accum_fn); | ||||
| DEFINE_DISPATCH(masked_select_serial_stub); | ||||
| DEFINE_DISPATCH(masked_select_stub); | ||||
|  | ||||
| DEFINE_DISPATCH(gather_stub); | ||||
| DEFINE_DISPATCH(scatter_stub); | ||||
| @ -629,82 +627,6 @@ Tensor masked_fill(const Tensor & self, const Tensor & mask, const Tensor & sour | ||||
|   return result; | ||||
| } | ||||
|  | ||||
| static Tensor & masked_select_out_impl_cpu(Tensor & result, const Tensor & self, const Tensor & mask) { | ||||
|   NoNamesGuard guard; | ||||
|  | ||||
|   TORCH_CHECK(mask.scalar_type() == ScalarType::Byte || mask.scalar_type() == ScalarType::Bool, | ||||
|               "masked_select: expected BoolTensor or ByteTensor for mask"); | ||||
|   TORCH_CHECK(self.scalar_type() == result.scalar_type(), | ||||
|               "masked_select(): self and result must have the same scalar type"); | ||||
|  | ||||
|   if (mask.dtype() == at::ScalarType::Byte) { | ||||
|     TORCH_WARN("masked_select received a mask with dtype torch.uint8, this behavior is now deprecated," \ | ||||
|             "please use a mask with dtype torch.bool instead."); | ||||
|   } | ||||
|  | ||||
|   Tensor _mask, _self; | ||||
|   std::tie(_mask, _self) = expand_outplace(mask, self); | ||||
|  | ||||
|   auto shape = _self.sizes(); | ||||
|   int64_t numel = _mask.sum().item().toLong(); | ||||
|   result.resize_({numel}); | ||||
|   if (numel == 0) { | ||||
|     return result; | ||||
|   } | ||||
|  | ||||
|   // Create strided view of result before feeding into TensorIterator | ||||
|   auto strides = DimVector(shape.size(), 0); | ||||
|   auto result_strided = result.as_strided(shape, strides); | ||||
|  | ||||
|   // serial kernel | ||||
|   bool use_serial_kernel = self.numel() < at::internal::GRAIN_SIZE || at::get_num_threads() == 1; | ||||
|   if (use_serial_kernel) { | ||||
|     auto iter = TensorIteratorConfig() | ||||
|       .check_all_same_dtype(false) | ||||
|       .resize_outputs(false) | ||||
|       .add_output(result_strided) | ||||
|       .add_input(_self) | ||||
|       .add_input(_mask) | ||||
|       .build(); | ||||
|  | ||||
|     masked_select_serial_stub(iter.device_type(), iter); | ||||
|     return result; | ||||
|   } | ||||
|  | ||||
|   // Use a prefix sum to record the output locations of the masked elements, | ||||
|   // so as to parallel with TensorIterator. | ||||
|   auto mask_long = at::empty(shape, self.options().dtype(at::kLong)).copy_(_mask); | ||||
|   auto mask_prefix_sum = at::empty(shape, self.options().dtype(at::kLong)); | ||||
|   auto mask_long_data = mask_long.data_ptr<int64_t>(); | ||||
|   auto mask_prefix_sum_data = mask_prefix_sum.data_ptr<int64_t>(); | ||||
|   // TODO: Here can only use std::partial_sum for C++14, | ||||
|   // use std::exclusive_scan when PyTorch upgrades to C++17, which have better peformance. | ||||
|   // std::exclusive_scan(mask_long_data, mask_long_data + mask_long.numel(), mask_prefix_sum_data, 0); | ||||
|   std::partial_sum(mask_long_data, mask_long_data + mask_long.numel(), mask_prefix_sum_data); | ||||
|  | ||||
|   auto iter = TensorIteratorConfig() | ||||
|     .check_all_same_dtype(false) | ||||
|     .resize_outputs(false) | ||||
|     .add_output(result_strided) | ||||
|     .add_input(_self) | ||||
|     .add_input(_mask) | ||||
|     .add_input(mask_prefix_sum) | ||||
|     .build(); | ||||
|  | ||||
|   masked_select_stub(iter.device_type(), iter); | ||||
|   return result; | ||||
| } | ||||
|  | ||||
| Tensor & masked_select_out_cpu(Tensor & result, const Tensor & self, const Tensor & mask) { | ||||
|   namedinference::compute_broadcast_outnames(self, mask); | ||||
|   return masked_select_out_impl_cpu(result, self, mask); | ||||
| } | ||||
|  | ||||
| Tensor masked_select_cpu(const Tensor & self, const Tensor & mask) { | ||||
|   Tensor result = at::empty({0}, self.options()); | ||||
|   return masked_select_out_cpu(result, self, mask); | ||||
| } | ||||
|  | ||||
| Tensor _gather_sparse_backward(const Tensor& self, int64_t dim, const Tensor& index, const Tensor& grad){ | ||||
| // special case scalar input and/or index | ||||
|     if (self.ndimension() == 0) return at::_sparse_coo_tensor_unsafe(at::empty({0,grad.numel()}, index.options()), grad, self.sizes()); | ||||
|  | ||||
| @ -15,7 +15,6 @@ using index_fn = void(*)(TensorIterator &, IntArrayRef indexed_sizes, IntArrayRe | ||||
| using index_put_fn = void(*)(TensorIterator &, IntArrayRef indexed_sizes, IntArrayRef indexed_strides, bool accumulate); | ||||
| using index_put_accum_fn = void(*)(Tensor &, TensorList , const Tensor &, bool unsafe); | ||||
| using masked_fill_fn = void(*)(TensorIterator &, Scalar scalar); | ||||
| using masked_select_fn = void(*)(TensorIterator &); | ||||
|  | ||||
| using gather_fn = void (*)(Tensor & result, const Tensor & self, int64_t dim, const Tensor & index); | ||||
| using scatter_fn = void(*)(Tensor& self, int64_t dim, const Tensor& index, const Tensor& src); | ||||
| @ -26,8 +25,6 @@ DECLARE_DISPATCH(index_fn, index_stub); | ||||
| DECLARE_DISPATCH(index_put_fn, index_put_stub); | ||||
| DECLARE_DISPATCH(index_put_accum_fn, index_put_accum_stub); | ||||
| DECLARE_DISPATCH(masked_fill_fn, masked_fill_stub); | ||||
| DECLARE_DISPATCH(masked_select_fn, masked_select_serial_stub); | ||||
| DECLARE_DISPATCH(masked_select_fn, masked_select_stub); | ||||
|  | ||||
| DECLARE_DISPATCH(gather_fn, gather_stub); | ||||
| DECLARE_DISPATCH(scatter_fn, scatter_stub); | ||||
|  | ||||
| @ -355,13 +355,12 @@ TensorOptions infer_full_options( | ||||
|  | ||||
|   if (!options.has_dtype()) { | ||||
|     if (fill_value.isIntegral(true)) { | ||||
|       TORCH_WARN_ONCE( | ||||
|         "Deprecation warning: In a future PyTorch release torch.full ", | ||||
|         "will no longer return tensors of floating dtype by default. ", | ||||
|         "Instead, a bool fill_value will return a tensor of torch.bool dtype, ", | ||||
|         "and an integral fill_value will return a tensor of torch.long dtype. ", | ||||
|         "Set the optional `dtype` or `out` arguments to suppress this warning." | ||||
|       ); | ||||
|       TORCH_CHECK(false, | ||||
|         "Providing a bool or integral fill value without setting the optional ", | ||||
|         "`dtype` or `out` arguments is currently unsupported. In PyTorch 1.7, ", | ||||
|         "when `dtype` and `out` are not set a bool fill value will ", | ||||
|         "return a tensor of torch.bool dtype, and an integral fill value ", | ||||
|         "will return a tensor of torch.long dtype."); | ||||
|     } else if (fill_value.isComplex()) { | ||||
|       auto scalar_type = (get_default_dtype() == ScalarType::Double) ? | ||||
|                             ScalarType::ComplexDouble : | ||||
|  | ||||
| @ -706,8 +706,9 @@ TensorIterator TensorIterator::unary_op(Tensor& out, const Tensor& a, | ||||
|     .set_check_mem_overlap(check_mem_overlap) | ||||
|     .add_output(out) | ||||
|     .add_input(a) | ||||
|     .cast_common_dtype_to_outputs(true) | ||||
|     .enforce_safe_casting_to_output(true) | ||||
|     .cast_common_dtype_to_outputs(false) | ||||
|     .enforce_safe_casting_to_output(false) | ||||
|     .check_all_same_dtype(true) | ||||
|     .build(); | ||||
| } | ||||
|  | ||||
|  | ||||
| @ -762,7 +762,12 @@ Tensor repeat(const Tensor& self, IntArrayRef repeats) { | ||||
|  | ||||
|   Tensor xtensor = self.expand(padded_size); | ||||
|  | ||||
|   Tensor result = at::empty(target_size, self.options()); | ||||
|   Tensor result; | ||||
|   if (self.is_quantized()) { | ||||
|     result = at::empty_quantized(target_size, self); | ||||
|   } else { | ||||
|     result = at::empty(target_size, self.options()); | ||||
|   } | ||||
|  | ||||
|   // return an empty tensor if one of the repeat dimensions is zero | ||||
|   if (zero_tensor) { | ||||
|  | ||||
| @ -67,7 +67,7 @@ static inline Tensor& unary_op_impl_with_complex_to_float_out(Tensor& result, co | ||||
|  | ||||
|       // Copies the complex result to the actual result and returns it | ||||
|       result.resize_(complex_result.sizes()); | ||||
|       result.copy_(complex_result); | ||||
|       result.copy_(at::real(complex_result)); | ||||
|       return result; | ||||
|     } | ||||
|  | ||||
|  | ||||
| @ -163,90 +163,11 @@ void masked_fill_kernel(TensorIterator& iter, Scalar value) { | ||||
|     }); | ||||
| } | ||||
|  | ||||
| template <typename scalar_t, typename mask_t, typename func_t> | ||||
| void cpu_masked_select_serial_kernel(TensorIterator& iter, const func_t& f) { | ||||
|   auto is_mask_bool = std::is_same<mask_t, bool>::value; | ||||
|   int64_t offset = 0; | ||||
|   auto loop = [&](char** data, const int64_t* strides, int64_t n) { | ||||
|     char* dst = data[0]; | ||||
|     char* src = data[1]; | ||||
|     char* mask = data[2]; | ||||
|     for (int64_t i = 0; i < n; i++) { | ||||
|       mask_t mask_value = *(mask_t*)(mask + strides[2] * i); | ||||
|       if (!is_mask_bool) { | ||||
|         TORCH_CHECK(mask_value == 0 || mask_value == 1, "Mask tensor can take 0 and 1 values only"); | ||||
|       } | ||||
|       if (mask_value) { | ||||
|         int64_t offset_bytes = offset * sizeof(scalar_t); | ||||
|         f(dst, src + strides[1] * i, offset_bytes); | ||||
|         offset++; | ||||
|       } | ||||
|     } | ||||
|   }; | ||||
|   iter.serial_for_each(loop, {0, iter.numel()}); | ||||
| } | ||||
|  | ||||
| void masked_select_serial_kernel(TensorIterator& iter) { | ||||
|   AT_DISPATCH_ALL_TYPES_AND_COMPLEX_AND2(at::ScalarType::Bool, at::ScalarType::BFloat16, | ||||
|     iter.dtype(), "masked_select", [&] { | ||||
|       auto mask_dtype = iter.input_dtype(1); | ||||
|       if (mask_dtype == at::ScalarType::Bool) { | ||||
|         cpu_masked_select_serial_kernel<scalar_t, bool>(iter, [](char* dst, char* src, int64_t offset) { | ||||
|           *(scalar_t*)(dst + offset) = *(scalar_t*)src; | ||||
|         }); | ||||
|       } else { | ||||
|         cpu_masked_select_serial_kernel<scalar_t, unsigned char>(iter, [](char* dst, char* src, int64_t offset) { | ||||
|           *(scalar_t*)(dst + offset) = *(scalar_t*)src; | ||||
|         }); | ||||
|       } | ||||
|     }); | ||||
| } | ||||
|  | ||||
| template <typename scalar_t, typename mask_t, typename func_t> | ||||
| void cpu_masked_select_kernel(TensorIterator& iter, const func_t& f) { | ||||
|   auto is_mask_bool = std::is_same<mask_t, bool>::value; | ||||
|   auto loop = [&](char** data, const int64_t* strides, int64_t n) { | ||||
|     char* dst = data[0]; | ||||
|     char* src = data[1]; | ||||
|     char* mask = data[2]; | ||||
|     char* mask_prefix_sum = data[3]; | ||||
|     for (int64_t i = 0; i < n; i++) { | ||||
|       mask_t mask_value = *(mask_t*)(mask + strides[2] * i); | ||||
|       if (!is_mask_bool) { | ||||
|         TORCH_CHECK(mask_value == 0 || mask_value == 1, "Mask tensor can take 0 and 1 values only"); | ||||
|       } | ||||
|       if (mask_value) { | ||||
|         int64_t offset = *(int64_t*)(mask_prefix_sum + strides[3] * i); | ||||
|         int64_t offset_bytes = (offset - 1) * sizeof(scalar_t); | ||||
|         f(dst, src + strides[1] * i, offset_bytes); | ||||
|       } | ||||
|     } | ||||
|   }; | ||||
|   iter.for_each(loop); | ||||
| } | ||||
|  | ||||
| void masked_select_kernel(TensorIterator& iter) { | ||||
|   AT_DISPATCH_ALL_TYPES_AND_COMPLEX_AND2(at::ScalarType::Bool, at::ScalarType::BFloat16, | ||||
|     iter.dtype(), "masked_select", [&] { | ||||
|       auto mask_dtype = iter.input_dtype(1); | ||||
|       if (mask_dtype == at::ScalarType::Bool) { | ||||
|         cpu_masked_select_kernel<scalar_t, bool>(iter, [](char* dst, char* src, int64_t offset) { | ||||
|           *(scalar_t*)(dst + offset) = *(scalar_t*)src; | ||||
|         }); | ||||
|       } else { | ||||
|         cpu_masked_select_kernel<scalar_t, unsigned char>(iter, [](char* dst, char* src, int64_t offset) { | ||||
|           *(scalar_t*)(dst + offset) = *(scalar_t*)src; | ||||
|         }); | ||||
|       } | ||||
|     }); | ||||
| } | ||||
|  | ||||
| } // anonymous namespace | ||||
|  | ||||
|  | ||||
| REGISTER_DISPATCH(index_stub, &index_kernel); | ||||
| REGISTER_DISPATCH(index_put_stub, &index_put_kernel); | ||||
| REGISTER_DISPATCH(masked_fill_stub, &masked_fill_kernel); | ||||
| REGISTER_DISPATCH(masked_select_serial_stub, &masked_select_serial_kernel); | ||||
| REGISTER_DISPATCH(masked_select_stub, &masked_select_kernel); | ||||
|  | ||||
| }} // namespace at::native | ||||
|  | ||||
| @ -1127,6 +1127,12 @@ | ||||
|   variants: method | ||||
|   device_guard: False | ||||
|  | ||||
| - func: empty_quantized(int[] size, Tensor qtensor) -> Tensor | ||||
|   variants: function | ||||
|   dispatch: | ||||
|     QuantizedCPU: empty_quantized | ||||
|     QuantizedCUDA: empty_quantized | ||||
|  | ||||
| - func: empty.out(int[] size, *, MemoryFormat? memory_format=None, Tensor(a!) out) -> Tensor(a!) | ||||
|   device_guard: False | ||||
|  | ||||
| @ -5108,6 +5114,8 @@ | ||||
|   dispatch: | ||||
|     CPU: unfold | ||||
|     CUDA: unfold | ||||
|     QuantizedCPU: unfold | ||||
|     QuantizedCUDA: unfold | ||||
|  | ||||
| - func: unfold_backward(Tensor grad_in, int[] input_sizes, int dim, int size, int step) -> Tensor | ||||
|   variants: function | ||||
|  | ||||
| @ -76,5 +76,28 @@ Tensor empty_per_channel_affine_quantized_other_backends_stub( | ||||
|   TORCH_CHECK(false, "Creation of quantized tensor requires quantized dtype like torch.quint8"); | ||||
| } | ||||
|  | ||||
| // Create an empty quantized Tensor with size, based on the options | ||||
| // and quantization parameters of the input quantized Tensor | ||||
| Tensor empty_quantized(IntArrayRef size, const Tensor& qtensor) { | ||||
|   Tensor output; | ||||
|   if (qtensor.qscheme() == kPerTensorAffine) { | ||||
|     output = at::_empty_affine_quantized(size, qtensor.options(), | ||||
|                                          qtensor.q_scale(), | ||||
|                                          qtensor.q_zero_point()); | ||||
|   } else if (qtensor.qscheme() == kPerChannelAffine) { | ||||
|     output = at::_empty_per_channel_affine_quantized( | ||||
|         size, | ||||
|         qtensor.q_per_channel_scales(), | ||||
|         qtensor.q_per_channel_zero_points(), | ||||
|         qtensor.q_per_channel_axis(), | ||||
|         qtensor.options()); | ||||
|   } else { | ||||
|     TORCH_CHECK(false, | ||||
|                 "QScheme not supported by empty_quantized:", | ||||
|                 toString(qtensor.qscheme())); | ||||
|   } | ||||
|   return output; | ||||
| } | ||||
|  | ||||
| } // namespace native | ||||
| } // namespace at | ||||
|  | ||||
| @ -5,7 +5,7 @@ | ||||
| #include <ATen/native/quantized/cpu/init_qnnpack.h> | ||||
| #include <ATen/native/quantized/cpu/qnnpack_utils.h> | ||||
| #include <ATen/native/quantized/cpu/quantized_ops.h> | ||||
| #include <caffe2/utils/threadpool/ThreadPoolMobile.h> | ||||
| #include <caffe2/utils/threadpool/pthreadpool-cpp.h> | ||||
| #include <c10/util/math_compat.h> | ||||
|  | ||||
| #include <algorithm> | ||||
| @ -375,7 +375,7 @@ Tensor qnnpack_avg_pool2d( | ||||
|   CAFFE_ENFORCE( | ||||
|       setupStatus == pytorch_qnnp_status_success, | ||||
|       "failed to setup QNNPACK Average Pooling operator"); | ||||
|   pthreadpool_t threadpool = caffe2::mobile_pthreadpool(); | ||||
|   pthreadpool_t threadpool = caffe2::pthreadpool_(); | ||||
|   const pytorch_qnnp_status runStatus = | ||||
|       pytorch_qnnp_run_operator(qnnpack_operator, threadpool); | ||||
|   TORCH_INTERNAL_ASSERT( | ||||
|  | ||||
| @ -5,7 +5,6 @@ | ||||
| #include <ATen/native/quantized/cpu/init_qnnpack.h> | ||||
| #include <ATen/native/quantized/cpu/qnnpack_utils.h> | ||||
| #include <ATen/native/quantized/cpu/quantized_ops.h> | ||||
| #include <caffe2/utils/threadpool/ThreadPoolMobile.h> | ||||
| #include <c10/util/math_compat.h> | ||||
|  | ||||
| #include <algorithm> | ||||
|  | ||||
| @ -7,7 +7,7 @@ | ||||
| #include <ATen/native/quantized/cpu/quantized_ops.h> | ||||
| #include <ATen/native/quantized/cpu/init_qnnpack.h> | ||||
| #include <ATen/native/quantized/cpu/qnnpack_utils.h> | ||||
| #include <caffe2/utils/threadpool/ThreadPoolMobile.h> | ||||
| #include <caffe2/utils/threadpool/pthreadpool-cpp.h> | ||||
|  | ||||
| #include <algorithm> | ||||
|  | ||||
| @ -194,7 +194,7 @@ Tensor qnnpack_add(Tensor qa, Tensor qb, double scale, int64_t zero_point) { | ||||
|       setupStatus == pytorch_qnnp_status_success, | ||||
|       "failed to setup QNNPACK Add operator"); | ||||
|  | ||||
|   pthreadpool_t threadpool = caffe2::mobile_pthreadpool(); | ||||
|   pthreadpool_t threadpool = caffe2::pthreadpool_(); | ||||
|   const pytorch_qnnp_status runStatus = | ||||
|       pytorch_qnnp_run_operator(qnnpack_operator, threadpool); | ||||
|  | ||||
|  | ||||
| @ -8,7 +8,7 @@ | ||||
| #include <ATen/native/quantized/cpu/init_qnnpack.h> | ||||
| #include <ATen/native/quantized/cpu/qnnpack_utils.h> | ||||
| #include <c10/core/TensorOptions.h> | ||||
| #include <caffe2/utils/threadpool/ThreadPoolMobile.h> | ||||
| #include <caffe2/utils/threadpool/pthreadpool-cpp.h> | ||||
|  | ||||
| #include <algorithm> | ||||
|  | ||||
| @ -82,7 +82,7 @@ Tensor quantized_channel_shuffle_impl( | ||||
|       setupStatus == pytorch_qnnp_status_success, | ||||
|       "failed to setup QNNPACK ChannelShuffle operator"); | ||||
|  | ||||
|   pthreadpool_t threadpool = caffe2::mobile_pthreadpool(); | ||||
|   pthreadpool_t threadpool = caffe2::pthreadpool_(); | ||||
|   const pytorch_qnnp_status runStatus = | ||||
|       pytorch_qnnp_run_operator(qnnpack_operator, threadpool); | ||||
|   TORCH_INTERNAL_ASSERT( | ||||
|  | ||||
| @ -7,7 +7,7 @@ | ||||
| #include <ATen/native/quantized/cpu/init_qnnpack.h> | ||||
| #include <ATen/native/quantized/cpu/qnnpack_utils.h> | ||||
| #include <ATen/quantized/Quantizer.h> | ||||
| #include <caffe2/utils/threadpool/ThreadPoolMobile.h> | ||||
| #include <caffe2/utils/threadpool/pthreadpool-cpp.h> | ||||
|  | ||||
| #include <algorithm> | ||||
|  | ||||
| @ -64,7 +64,7 @@ Tensor qnnpack_clamp(Tensor input, Scalar min, Scalar max) { | ||||
|   TORCH_INTERNAL_ASSERT(setupStatus == pytorch_qnnp_status_success, | ||||
|                         "failed to setup QNNPACK Clamp operator"); | ||||
|  | ||||
|   pthreadpool_t threadpool = caffe2::mobile_pthreadpool(); | ||||
|   pthreadpool_t threadpool = caffe2::pthreadpool_(); | ||||
|  | ||||
|   const pytorch_qnnp_status runStatus = | ||||
|     pytorch_qnnp_run_operator(clamp_op, threadpool); | ||||
|  | ||||
| @ -10,7 +10,7 @@ | ||||
| #include <ATen/native/quantized/cpu/qnnpack_utils.h> | ||||
| #include <ATen/native/quantized/cpu/quant_utils.h> | ||||
| #include <ATen/native/quantized/cpu/conv_packed_params.h> | ||||
| #include <caffe2/utils/threadpool/ThreadPoolMobile.h> | ||||
| #include <caffe2/utils/threadpool/pthreadpool-cpp.h> | ||||
|  | ||||
| template <int kSpatialDim = 2> | ||||
| bool ConvDimChecks( | ||||
| @ -603,7 +603,7 @@ at::Tensor PackedConvWeightsQnnp<kSpatialDim>::apply_impl( | ||||
|       output_min, | ||||
|       output_max, | ||||
|       reinterpret_cast<uint8_t*>(output.template data_ptr<c10::quint8>()), | ||||
|       caffe2::mobile_pthreadpool()); | ||||
|       caffe2::pthreadpool_()); | ||||
|  | ||||
|   TORCH_INTERNAL_ASSERT( | ||||
|       run_status == pytorch_qnnp_status_success, | ||||
|  | ||||
| @ -5,7 +5,7 @@ | ||||
| #include <ATen/native/quantized/cpu/quantized_ops.h> | ||||
| #include <ATen/native/quantized/cpu/init_qnnpack.h> | ||||
| #include <ATen/native/quantized/cpu/qnnpack_utils.h> | ||||
| #include <caffe2/utils/threadpool/ThreadPoolMobile.h> | ||||
| #include <caffe2/utils/threadpool/pthreadpool-cpp.h> | ||||
|  | ||||
| #include <algorithm> | ||||
|  | ||||
| @ -57,7 +57,7 @@ Tensor qnnpack_hardsigmoid(Tensor input) { | ||||
|   TORCH_INTERNAL_ASSERT(setupStatus == pytorch_qnnp_status_success, | ||||
|                         "failed to setup QNNPACK Hardsigmoid operator"); | ||||
|  | ||||
|   pthreadpool_t threadpool = caffe2::mobile_pthreadpool(); | ||||
|   pthreadpool_t threadpool = caffe2::pthreadpool_(); | ||||
|  | ||||
|   const pytorch_qnnp_status runStatus = | ||||
|     pytorch_qnnp_run_operator(hardsigmoid_op, threadpool); | ||||
|  | ||||
| @ -5,7 +5,7 @@ | ||||
| #include <ATen/native/quantized/cpu/quantized_ops.h> | ||||
| #include <ATen/native/quantized/cpu/init_qnnpack.h> | ||||
| #include <ATen/native/quantized/cpu/qnnpack_utils.h> | ||||
| #include <caffe2/utils/threadpool/ThreadPoolMobile.h> | ||||
| #include <caffe2/utils/threadpool/pthreadpool-cpp.h> | ||||
|  | ||||
| #include <algorithm> | ||||
|  | ||||
| @ -51,7 +51,7 @@ Tensor qnnpack_hardswish(const Tensor& qx, Tensor& qy) { | ||||
|   TORCH_INTERNAL_ASSERT(setupStatus == pytorch_qnnp_status_success, | ||||
|                         "failed to setup QNNPACK Hardswish operator"); | ||||
|  | ||||
|   pthreadpool_t threadpool = caffe2::mobile_pthreadpool(); | ||||
|   pthreadpool_t threadpool = caffe2::pthreadpool_(); | ||||
|  | ||||
|   const pytorch_qnnp_status runStatus = | ||||
|     pytorch_qnnp_run_operator(hardswish_op, threadpool); | ||||
|  | ||||
| @ -4,7 +4,7 @@ | ||||
| #include <ATen/native/quantized/cpu/fbgemm_utils.h> | ||||
| #include <ATen/native/quantized/cpu/packed_params.h> | ||||
| #include <ATen/native/quantized/cpu/qnnpack_utils.h> | ||||
| #include <caffe2/utils/threadpool/ThreadPoolMobile.h> | ||||
| #include <caffe2/utils/threadpool/pthreadpool-cpp.h> | ||||
| #include <torch/custom_class.h> | ||||
| #include <torch/library.h> | ||||
|  | ||||
| @ -341,7 +341,9 @@ at::Tensor PackedLinearWeightsQnnp::apply_impl( | ||||
|       packB->getPackedWeights(), | ||||
|       (uint8_t*)output.data_ptr<c10::quint8>(), | ||||
|       rows_w /* output_stride */, | ||||
|       caffe2::mobile_pthreadpool() /* threadpool */); | ||||
|       // TODO (Ashkan): Disabling temporarily. | ||||
|       // Throws a floating point exception with OSS pthreadpool. | ||||
|       caffe2::pthreadpool_() /* threadpool */); | ||||
|  | ||||
|   TORCH_INTERNAL_ASSERT( | ||||
|       runStatus == pytorch_qnnp_status_success, | ||||
|  | ||||
| @ -5,7 +5,7 @@ | ||||
| #include <ATen/native/quantized/cpu/packed_params.h> | ||||
| #include <ATen/native/quantized/cpu/qnnpack_utils.h> | ||||
| #include <ATen/native/quantized/cpu/quant_utils.h> | ||||
| #include <caffe2/utils/threadpool/ThreadPoolMobile.h> | ||||
| #include <caffe2/utils/threadpool/pthreadpool-cpp.h> | ||||
| #include <torch/library.h> | ||||
|  | ||||
| #include <torch/custom_class.h> | ||||
| @ -241,8 +241,17 @@ at::Tensor PackedLinearWeightsQnnp::apply_dynamic_impl(at::Tensor input) { | ||||
|  | ||||
|   // Calculate statistics for quantization of input Tensor | ||||
|   // TODO: optimized kernel | ||||
|   float x_min = input_contig.min().item<float>(); | ||||
|   float x_max = input_contig.max().item<float>(); | ||||
|   float x_min; | ||||
|   float x_max; | ||||
|   if (input.numel() > 0) { | ||||
|     x_min = input_contig.min().item<float>(); | ||||
|     x_max = input_contig.max().item<float>(); | ||||
|   } else { | ||||
|     // On empty input, no output data will be generated, | ||||
|     // so use arbitrary qparams. | ||||
|     x_min = 0; | ||||
|     x_max = 0; | ||||
|   } | ||||
|  | ||||
|   auto q_params = quant_utils::ChooseQuantizationParams( | ||||
|       /*min=*/x_min, | ||||
| @ -327,7 +336,7 @@ at::Tensor PackedLinearWeightsQnnp::apply_dynamic_impl(at::Tensor input) { | ||||
|       bias_ptr, | ||||
|       output.data_ptr<float>(), | ||||
|       rows_w /* output_stride */, | ||||
|       caffe2::mobile_pthreadpool() /* threadpool */); | ||||
|       caffe2::pthreadpool_() /* threadpool */); | ||||
|  | ||||
|   TORCH_INTERNAL_ASSERT( | ||||
|       runStatus == pytorch_qnnp_status_success, | ||||
|  | ||||
| @ -100,6 +100,12 @@ enum pytorch_qnnp_status qnnpackLinearDynamic( | ||||
|       .ukernel = pytorch_qnnp_params.q8conv.gemm_dq, | ||||
|   }; | ||||
|  | ||||
|   if (output_size == 0) { | ||||
|       // pthreadpool can tolerate a range of 0, but not a tile of 0. | ||||
|       // We use output_size as a tile size, so bail here if it's 0. | ||||
|       return pytorch_qnnp_status_success; | ||||
|   } | ||||
|  | ||||
|   pthreadpool_compute_4d_tiled( | ||||
|       threadpool, | ||||
|       (pthreadpool_function_4d_tiled_t)compute_q8gemm_dq, | ||||
|  | ||||
| @ -98,6 +98,12 @@ enum pytorch_qnnp_status qnnpackLinear( | ||||
|       .ukernel = pytorch_qnnp_params.q8conv.gemm, | ||||
|   }; | ||||
|  | ||||
|   if (output_size == 0) { | ||||
|       // pthreadpool can tolerate a range of 0, but not a tile of 0. | ||||
|       // We use output_size as a tile size, so bail here if it's 0. | ||||
|       return pytorch_qnnp_status_success; | ||||
|   } | ||||
|  | ||||
|   pthreadpool_compute_4d_tiled( | ||||
|       threadpool, | ||||
|       (pthreadpool_function_4d_tiled_t) compute_q8gemm, | ||||
|  | ||||
| @ -9,7 +9,7 @@ | ||||
| #include <ATen/native/quantized/cpu/quantized_ops.h> | ||||
| #include <ATen/native/quantized/cpu/init_qnnpack.h> | ||||
| #include <ATen/native/quantized/cpu/qnnpack_utils.h> | ||||
| #include <caffe2/utils/threadpool/ThreadPoolMobile.h> | ||||
| #include <caffe2/utils/threadpool/pthreadpool-cpp.h> | ||||
|  | ||||
| #include <algorithm> | ||||
| #include <vector> | ||||
| @ -346,7 +346,7 @@ void check_maxpool2d_params( | ||||
|        setupStatus == pytorch_qnnp_status_success, | ||||
|        "failed to setup QNNPACK MaxPool operator"); | ||||
|  | ||||
|    pthreadpool_t threadpool = caffe2::mobile_pthreadpool(); | ||||
|    pthreadpool_t threadpool = caffe2::pthreadpool_(); | ||||
|    const pytorch_qnnp_status runStatus = | ||||
|        pytorch_qnnp_run_operator(qnnpack_operator, threadpool); | ||||
|    TORCH_INTERNAL_ASSERT( | ||||
|  | ||||
| @ -3,7 +3,7 @@ | ||||
| #include <ATen/NativeFunctions.h> | ||||
| #include <ATen/native/quantized/cpu/init_qnnpack.h> | ||||
| #include <ATen/native/quantized/cpu/qnnpack_utils.h> | ||||
| #include <caffe2/utils/threadpool/ThreadPoolMobile.h> | ||||
| #include <caffe2/utils/threadpool/pthreadpool-cpp.h> | ||||
|  | ||||
| namespace at { | ||||
| namespace native { | ||||
| @ -66,7 +66,7 @@ Tensor qnnpack_mean(const Tensor& input, IntArrayRef dim) { | ||||
|   CAFFE_ENFORCE( | ||||
|       setupStatus == pytorch_qnnp_status_success, | ||||
|       "failed to setup QNNPACK Global Average Pooling operator"); | ||||
|   pthreadpool_t threadpool = caffe2::mobile_pthreadpool(); | ||||
|   pthreadpool_t threadpool = caffe2::pthreadpool_(); | ||||
|   const pytorch_qnnp_status runStatus = | ||||
|       pytorch_qnnp_run_operator(qnnpack_operator, threadpool); | ||||
|   TORCH_INTERNAL_ASSERT( | ||||
|  | ||||
| @ -6,7 +6,7 @@ | ||||
| #include <ATen/native/quantized/cpu/init_qnnpack.h> | ||||
| #include <ATen/native/quantized/cpu/qnnpack_utils.h> | ||||
| #include <ATen/native/quantized/cpu/quantized_ops.h> | ||||
| #include <caffe2/utils/threadpool/ThreadPoolMobile.h> | ||||
| #include <caffe2/utils/threadpool/pthreadpool-cpp.h> | ||||
| #include <torch/library.h> | ||||
|  | ||||
| #include <algorithm> | ||||
| @ -69,7 +69,7 @@ Tensor qnnpack_relu(Tensor input) { | ||||
|       setupStatus == pytorch_qnnp_status_success, | ||||
|       "failed to setup QNNPACK Relu operator"); | ||||
|  | ||||
|   pthreadpool_t threadpool = caffe2::mobile_pthreadpool(); | ||||
|   pthreadpool_t threadpool = caffe2::pthreadpool_(); | ||||
|  | ||||
|   const pytorch_qnnp_status runStatus = | ||||
|       pytorch_qnnp_run_operator(qnnpack_operator, threadpool); | ||||
|  | ||||
| @ -7,7 +7,7 @@ | ||||
| #include <ATen/native/quantized/cpu/quantized_ops.h> | ||||
| #include <ATen/native/quantized/cpu/init_qnnpack.h> | ||||
| #include <ATen/native/quantized/cpu/qnnpack_utils.h> | ||||
| #include <caffe2/utils/threadpool/ThreadPoolMobile.h> | ||||
| #include <caffe2/utils/threadpool/pthreadpool-cpp.h> | ||||
|  | ||||
| #include <algorithm> | ||||
|  | ||||
| @ -66,7 +66,7 @@ Tensor qnnpack_sigmoid(Tensor input) { | ||||
|   TORCH_INTERNAL_ASSERT(setupStatus == pytorch_qnnp_status_success, | ||||
|                         "failed to setup QNNPACK sigmoid operator"); | ||||
|  | ||||
|   pthreadpool_t threadpool = caffe2::mobile_pthreadpool(); | ||||
|   pthreadpool_t threadpool = caffe2::pthreadpool_(); | ||||
|  | ||||
|   const pytorch_qnnp_status runStatus = | ||||
|     pytorch_qnnp_run_operator(sigmoid_op, threadpool); | ||||
|  | ||||
| @ -7,7 +7,7 @@ | ||||
| #include <ATen/native/quantized/cpu/quantized_ops.h> | ||||
| #include <ATen/native/quantized/cpu/init_qnnpack.h> | ||||
| #include <ATen/native/quantized/cpu/qnnpack_utils.h> | ||||
| #include <caffe2/utils/threadpool/ThreadPoolMobile.h> | ||||
| #include <caffe2/utils/threadpool/pthreadpool-cpp.h> | ||||
|  | ||||
| #include <algorithm> | ||||
|  | ||||
| @ -64,7 +64,7 @@ Tensor qnnpack_tanh(Tensor input) { | ||||
|   TORCH_INTERNAL_ASSERT(setupStatus == pytorch_qnnp_status_success, | ||||
|                         "failed to setup QNNPACK TanH operator"); | ||||
|  | ||||
|   pthreadpool_t threadpool = caffe2::mobile_pthreadpool(); | ||||
|   pthreadpool_t threadpool = caffe2::pthreadpool_(); | ||||
|  | ||||
|   const pytorch_qnnp_status runStatus = | ||||
|     pytorch_qnnp_run_operator(tanh_op, threadpool); | ||||
|  | ||||
| @ -5,7 +5,7 @@ | ||||
| #ifdef USE_XNNPACK | ||||
|  | ||||
| #include <xnnpack.h> | ||||
| #include <caffe2/utils/threadpool/ThreadPoolXNNPACK.h> | ||||
| #include <caffe2/utils/threadpool/pthreadpool-cpp.h> | ||||
|  | ||||
| namespace at { | ||||
| namespace native { | ||||
|  | ||||
| @ -208,15 +208,15 @@ Tensor run( | ||||
|       padded_input_nhwc.size(Layout::Activation4D::width),   // input_width | ||||
|       padded_input_nhwc.data_ptr<float>(),                   // input | ||||
|       output.data_ptr<float>(),                              // output | ||||
|       caffe2::xnnpack_threadpool());                         // threadpool | ||||
|       caffe2::pthreadpool_());                               // threadpool | ||||
|  | ||||
|   TORCH_CHECK( | ||||
|       xnn_status_success == setup_status, | ||||
|       "xnn_setup_convolution2d_nhwc_f32 failed!"); | ||||
|  | ||||
|   const xnn_status run_status = xnn_run_operator( | ||||
|       context.op.get(),               // operator | ||||
|       caffe2::xnnpack_threadpool());  // threadpool | ||||
|       context.op.get(),         // operator | ||||
|       caffe2::pthreadpool_());  // threadpool | ||||
|  | ||||
|   TORCH_INTERNAL_ASSERT( | ||||
|       xnn_status_success == run_status, | ||||
|  | ||||
| @ -137,15 +137,15 @@ Tensor run( | ||||
|       Layout::ActivationND::batch(padded_input.sizes()),  // Batch, | ||||
|       padded_input.data_ptr<float>(),                     // input | ||||
|       output.data_ptr<float>(),                           // output | ||||
|       caffe2::xnnpack_threadpool());                      // threadpool | ||||
|       caffe2::pthreadpool_());                            // threadpool | ||||
|  | ||||
|   TORCH_CHECK( | ||||
|       xnn_status_success == setup_status, | ||||
|       "xnn_setup_fully_connected_nc_f32 failed!"); | ||||
|  | ||||
|   const xnn_status run_status = xnn_run_operator( | ||||
|       context.op.get(),               // operator | ||||
|       caffe2::xnnpack_threadpool());  // threadpool | ||||
|       context.op.get(),         // operator | ||||
|       caffe2::pthreadpool_());  // threadpool | ||||
|  | ||||
|   TORCH_INTERNAL_ASSERT( | ||||
|       xnn_status_success == run_status, | ||||
|  | ||||
| @ -219,15 +219,15 @@ Tensor max_pool2d( | ||||
|       input_padded_contig_nhwc.size(Layout::Activation4D::width),   // input_width | ||||
|       input_padded_contig_nhwc.data_ptr<float>(),                   // input | ||||
|       output_padded_contig_nhwc.data_ptr<float>(),                  // output | ||||
|       caffe2::xnnpack_threadpool());                                // threadpool | ||||
|       caffe2::pthreadpool_());                                      // threadpool | ||||
|  | ||||
|   TORCH_CHECK( | ||||
|       xnn_status_success == setup_status, | ||||
|       "xnn_setup_max_pooling2d_nhwc_f32 failed!"); | ||||
|  | ||||
|   const xnn_status run_status = xnn_run_operator( | ||||
|       max_pool_op,                    // operator | ||||
|       caffe2::xnnpack_threadpool());  // threadpool | ||||
|       max_pool_op,              // operator | ||||
|       caffe2::pthreadpool_());  // threadpool | ||||
|  | ||||
|   TORCH_INTERNAL_ASSERT( | ||||
|       xnn_status_success == run_status, | ||||
|  | ||||
| @ -4,10 +4,10 @@ | ||||
| #include <ATen/NativeFunctions.h> | ||||
| #include <ATen/Parallel.h> | ||||
| #include <ATen/core/Tensor.h> | ||||
| #include <ATen/detail/CUDAHooksInterface.h> | ||||
| #include <ATen/native/TensorFactories.h> | ||||
| #include <ATen/native/quantized/affine_quantizer.h> | ||||
| #include <ATen/quantized/QTensorImpl.h> | ||||
| #include <c10/core/Allocator.h> | ||||
| #include <c10/core/CPUAllocator.h> | ||||
| #include <cmath> | ||||
| #include <typeinfo> | ||||
| @ -66,7 +66,9 @@ inline Tensor new_qtensor( | ||||
|     const TensorOptions& options, | ||||
|     QuantizerPtr quantizer) { | ||||
|   auto memory_format = options.memory_format_opt().value_or(MemoryFormat::Contiguous); | ||||
|   at::Allocator* allocator = GetAllocator(options.device().type()); | ||||
|   at::Allocator* allocator = options.device().type() == DeviceType::CUDA | ||||
|     ? at::detail::getCUDAHooks().getCUDADeviceAllocator() | ||||
|     : at::getCPUAllocator(); | ||||
|  | ||||
| #ifdef USE_PYTORCH_QNNPACK | ||||
|   if (at::globalContext().qEngine() == at::QEngine::QNNPACK) { | ||||
|  | ||||
| @ -99,6 +99,50 @@ accreal THTensor_(dot)(THTensor *tensor, THTensor *src) | ||||
|  | ||||
| #if !defined(TH_REAL_IS_HALF) /* non half part */ | ||||
|  | ||||
| void THTensor_(maskedSelect)(THTensor *tensor, THTensor *src, THByteTensor *mask) | ||||
| { | ||||
|   at::NoNamesGuard guard; | ||||
|   ptrdiff_t numel = THTensor_wrap(mask).sum().item<int64_t>(); | ||||
|   scalar_t *tensor_data; | ||||
|  | ||||
| #ifdef DEBUG | ||||
|   THAssert(numel <= LONG_MAX); | ||||
| #endif | ||||
|   THTensor_(resize1d)(tensor,numel); | ||||
|   tensor_data = tensor->data<scalar_t>(); | ||||
|   TH_TENSOR_APPLY2(scalar_t, src, unsigned char, mask, | ||||
|                    if (*mask_data > 1) | ||||
|                    { | ||||
|                      THFree(mask_counter); | ||||
|                      THFree(src_counter); | ||||
|                      THError("Mask tensor can take 0 and 1 values only"); | ||||
|                    } | ||||
|                    else if (*mask_data == 1) | ||||
|                    { | ||||
|                      *tensor_data = *src_data; | ||||
|                      tensor_data++; | ||||
|                    }); | ||||
| } | ||||
|  | ||||
| void THTensor_(maskedSelectBool)(THTensor *tensor, THTensor *src, THBoolTensor *mask) | ||||
| { | ||||
|   at::NoNamesGuard guard; | ||||
|   ptrdiff_t numel = THTensor_wrap(mask).sum().item<int64_t>(); | ||||
|   scalar_t *tensor_data; | ||||
|  | ||||
| #ifdef DEBUG | ||||
|   THAssert(numel <= LONG_MAX); | ||||
| #endif | ||||
|   THTensor_(resize1d)(tensor,numel); | ||||
|   tensor_data = tensor->data<scalar_t>(); | ||||
|   TH_TENSOR_APPLY2(scalar_t, src, bool, mask, | ||||
|                    if (*mask_data) | ||||
|                    { | ||||
|                      *tensor_data = *src_data; | ||||
|                      tensor_data++; | ||||
|                    }); | ||||
| } | ||||
|  | ||||
| void THTensor_(maskedCopy)(THTensor *tensor, THByteTensor *mask, THTensor* src ) | ||||
| { | ||||
|   THTensor *srct = THTensor_(newContiguous)(src); | ||||
|  | ||||
| @ -9,6 +9,8 @@ TH_API int THTensor_(equal)(THTensor *ta, THTensor *tb); | ||||
|  | ||||
| #if !defined(TH_REAL_IS_HALF) | ||||
|  | ||||
| TH_API void THTensor_(maskedSelect)(THTensor *tensor, THTensor* src, THByteTensor *mask); | ||||
| TH_API void THTensor_(maskedSelectBool)(THTensor *tensor, THTensor* src, THBoolTensor *mask); | ||||
| TH_API void THTensor_(maskedCopy)(THTensor *tensor, THByteTensor *mask, THTensor* src); | ||||
| TH_API void THTensor_(maskedCopyBool)(THTensor *tensor, THBoolTensor *mask, THTensor* src); | ||||
|  | ||||
|  | ||||
| @ -155,10 +155,16 @@ public: | ||||
|  | ||||
|   static std::tuple<int, int> priority_range() { | ||||
|     #ifndef __HIP_PLATFORM_HCC__ | ||||
|       // Note: this returns the range of priority **supported by PyTorch**, not | ||||
|       // the range of priority **supported by CUDA**. The former is a subset of | ||||
|       // the latter. Curently PyTorch only supports 0 and -1, which are "low" and | ||||
|       // "high" priority. | ||||
|       int least_priority, greatest_priority; | ||||
|       C10_CUDA_CHECK( | ||||
|         cudaDeviceGetStreamPriorityRange(&least_priority, &greatest_priority)); | ||||
|       return std::make_tuple(least_priority, greatest_priority); | ||||
|       TORCH_INTERNAL_ASSERT(least_priority >= 0, "Unexpected CUDA stream priority range"); | ||||
|       TORCH_INTERNAL_ASSERT(greatest_priority <= -1, "Unexpected CUDA stream priority range"); | ||||
|       return std::make_tuple(0, -1); | ||||
|     #else | ||||
|       AT_ERROR("cuDeviceGetStreamPriorityRange with HIP is not supported"); | ||||
|     #endif | ||||
|  | ||||
| @ -87,7 +87,6 @@ endif() | ||||
| # Note: the folders that are being commented out have not been properly | ||||
| # addressed yet. | ||||
|  | ||||
| # For pthreadpool_new_if_impl. TODO: Remove when threadpools are unitied. | ||||
| if(NOT MSVC AND USE_XNNPACK) | ||||
|   if(NOT TARGET fxdiv) | ||||
|     set(FXDIV_BUILD_TESTS OFF CACHE BOOL "") | ||||
| @ -96,10 +95,6 @@ if(NOT MSVC AND USE_XNNPACK) | ||||
|       "${FXDIV_SOURCE_DIR}" | ||||
|       "${CMAKE_BINARY_DIR}/FXdiv") | ||||
|   endif() | ||||
|   if(NOT (INTERN_BUILD_MOBILE AND NOT BUILD_CAFFE2_MOBILE)) | ||||
|     set_source_files_properties( | ||||
|         utils/threadpool/pthreadpool_new_if_impl.c PROPERTIES COMPILE_FLAGS -fno-openmp) | ||||
|   endif() | ||||
| endif() | ||||
|  | ||||
| add_subdirectory(core) | ||||
|  | ||||
| @ -818,6 +818,67 @@ c10::optional<int> OperatorBase::argumentIndexWithName( | ||||
| #endif | ||||
| } | ||||
|  | ||||
| bool OperatorBase::RunAsync(int stream_id) { | ||||
|   try { | ||||
|     auto result = Run(stream_id); | ||||
|     if (result) { | ||||
|       if (HasAsyncPart()) { | ||||
|         RecordEvent(); | ||||
|       } else { | ||||
|         SetEventFinished(); | ||||
|       } | ||||
|     } else { | ||||
|       SetEventFinished(getErrorMsg().c_str()); | ||||
|     } | ||||
|     return result; | ||||
|   } catch (EnforceNotMet& err) { | ||||
|     SetEventFinishedWithException(err.what()); | ||||
|     throw; | ||||
|   } catch (const std::exception& err) { | ||||
|     SetEventFinishedWithException(err.what()); | ||||
|     throw; | ||||
|   } catch (...) { | ||||
|     SetEventFinishedWithException(getErrorMsg().c_str()); | ||||
|     throw; | ||||
|   } | ||||
| } | ||||
|  | ||||
| void OperatorBase::AddRelatedBlobInfo(EnforceNotMet* err) { | ||||
|   CAFFE_ENFORCE( | ||||
|       isLegacyOperator(), | ||||
|       "AddRelatedBlobInfo(err) not supported for operators exported to c10."); | ||||
|  | ||||
|   if (!has_debug_def()) { | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   bool found_input = false; | ||||
|   bool found_output = false; | ||||
|   if (err->caller() != nullptr) { | ||||
|     std::ostringstream oss; | ||||
|     for (size_t i = 0; i < inputs_.size(); i++) { | ||||
|       if (inputs_[i]->GetRaw() == err->caller()) { | ||||
|         found_input = true; | ||||
|         oss << "while accessing input: " << debug_def().input(i); | ||||
|         break; | ||||
|       } | ||||
|     } | ||||
|     for (size_t i = 0; i < outputs_.size(); i++) { | ||||
|       if (outputs_[i]->GetRaw() == err->caller()) { | ||||
|         found_output = true; | ||||
|         if (found_input) { | ||||
|           oss << " OR "; | ||||
|         } | ||||
|         oss << "while accessing output: " << debug_def().output(i); | ||||
|         break; | ||||
|       } | ||||
|     } | ||||
|     if (found_input || found_output) { | ||||
|       err->add_context(oss.str()); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| OperatorBase::~OperatorBase() noexcept = default; | ||||
|  | ||||
| #ifndef C10_MOBILE | ||||
|  | ||||
| @ -480,70 +480,13 @@ class CAFFE2_API OperatorBase : public Observable<OperatorBase> { | ||||
|  | ||||
|   virtual void CancelAsyncCallback() {} | ||||
|  | ||||
|   // RunAsync, if implemenented by the specific operators, will schedule the | ||||
|   // RunAsync, if implemented by the specific operators, will schedule the | ||||
|   // computation on the corresponding context and record the event in its | ||||
|   // event_ member object. If the specific operator does not support RunAsync, | ||||
|   // it will simply be synchronous as a fallback. | ||||
|   virtual bool RunAsync(int stream_id = 0) { | ||||
|     try { | ||||
|       auto result = Run(stream_id); | ||||
|       if (result) { | ||||
|         if (HasAsyncPart()) { | ||||
|           RecordEvent(); | ||||
|         } else { | ||||
|           SetEventFinished(); | ||||
|         } | ||||
|       } else { | ||||
|         SetEventFinished(getErrorMsg().c_str()); | ||||
|       } | ||||
|       return result; | ||||
|     } catch (EnforceNotMet& err) { | ||||
|       SetEventFinishedWithException(err.what()); | ||||
|       throw; | ||||
|     } catch (const std::exception& err) { | ||||
|       SetEventFinishedWithException(err.what()); | ||||
|       throw; | ||||
|     } catch (...) { | ||||
|       SetEventFinishedWithException(getErrorMsg().c_str()); | ||||
|       throw; | ||||
|     } | ||||
|   } | ||||
|   virtual bool RunAsync(int stream_id = 0); | ||||
|  | ||||
|   virtual void AddRelatedBlobInfo(EnforceNotMet* err) { | ||||
|     CAFFE_ENFORCE( | ||||
|         isLegacyOperator(), | ||||
|         "AddRelatedBlobInfo(err) not supported for operators exported to c10."); | ||||
|  | ||||
|     if (!has_debug_def()) { | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     bool found_input = false; | ||||
|     bool found_output = false; | ||||
|     if (err->caller() != nullptr) { | ||||
|       std::ostringstream oss; | ||||
|       for (size_t i = 0; i < inputs_.size(); i++) { | ||||
|         if (inputs_[i]->GetRaw() == err->caller()) { | ||||
|           found_input = true; | ||||
|           oss << "while accessing input: " << debug_def().input(i); | ||||
|           break; | ||||
|         } | ||||
|       } | ||||
|       for (size_t i = 0; i < outputs_.size(); i++) { | ||||
|         if (outputs_[i]->GetRaw() == err->caller()) { | ||||
|           found_output = true; | ||||
|           if (found_input) { | ||||
|             oss << " OR "; | ||||
|           } | ||||
|           oss << "while accessing output: " << debug_def().output(i); | ||||
|           break; | ||||
|         } | ||||
|       } | ||||
|       if (found_input || found_output) { | ||||
|         err->add_context(oss.str()); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   virtual void AddRelatedBlobInfo(EnforceNotMet* err); | ||||
|  | ||||
|   virtual std::string debug_info_string() const { | ||||
|     return ""; | ||||
|  | ||||
| @ -3,6 +3,25 @@ | ||||
|  | ||||
| namespace caffe2 { | ||||
|  | ||||
| OpSchema::OpSchema(const string& type, const string& file, const int line) | ||||
|    : type_(type), file_(file), line_(line), tensor_inference_function_( | ||||
|       [](const OperatorDef& def, const vector<TensorShape>&) { | ||||
|         vector<TensorShape> out; | ||||
|         for (int i = 0; i < def.output_size(); i++) { | ||||
|           TensorShape ts; | ||||
|           ts.set_unknown_shape(true); | ||||
|           out.push_back(ts); | ||||
|         } | ||||
|         return out; | ||||
|       }), device_inference_function_( | ||||
|       [](const OperatorDef& def) { | ||||
|         auto op_device = | ||||
|             def.has_device_option() ? def.device_option() : DeviceOption(); | ||||
|         vector<DeviceOption> in_dev(def.input_size(), op_device); | ||||
|         vector<DeviceOption> out_dev(def.output_size(), op_device); | ||||
|         return std::make_pair(in_dev, out_dev); | ||||
|       }) {} | ||||
|  | ||||
| bool OpSchema::Verify(const OperatorDef& def) const { | ||||
|   // Check the number of inputs. | ||||
|   if (def.input_size() < min_input_ || def.input_size() > max_input_) { | ||||
|  | ||||
| @ -39,9 +39,8 @@ constexpr int kCannotComputeNumOutputs = -1; | ||||
|  */ | ||||
| class CAFFE2_API OpSchema { | ||||
|  public: | ||||
|   OpSchema() : type_("unknown"), file_("unknown"), line_(0) {} | ||||
|   OpSchema(const string& type, const string& file, const int line) | ||||
|       : type_(type), file_(file), line_(line) {} | ||||
|   OpSchema() : OpSchema("unknown", "unknown", 0) {} | ||||
|   OpSchema(const string& type, const string& file, const int line); | ||||
|  | ||||
|   /** | ||||
|    * @brief Returns the file that the op schema is registered from. | ||||
| @ -443,25 +442,9 @@ class CAFFE2_API OpSchema { | ||||
|   std::function<bool(int, int)> inplace_enforced_ = [](int, int) { | ||||
|     return false; | ||||
|   }; | ||||
|   TensorInferenceFunctionType tensor_inference_function_ = | ||||
|       [](const OperatorDef& def, const vector<TensorShape>&) { | ||||
|         vector<TensorShape> out; | ||||
|         for (int i = 0; i < def.output_size(); i++) { | ||||
|           TensorShape ts; | ||||
|           ts.set_unknown_shape(true); | ||||
|           out.push_back(ts); | ||||
|         } | ||||
|         return out; | ||||
|       }; | ||||
|   TensorInferenceFunctionType tensor_inference_function_; | ||||
|   std::unique_ptr<CostInferenceFunctionType> cost_inference_function_ = nullptr; | ||||
|   DeviceInferenceFunctionType device_inference_function_ = | ||||
|       [](const OperatorDef& def) { | ||||
|         auto op_device = | ||||
|             def.has_device_option() ? def.device_option() : DeviceOption(); | ||||
|         vector<DeviceOption> in_dev(def.input_size(), op_device); | ||||
|         vector<DeviceOption> out_dev(def.output_size(), op_device); | ||||
|         return std::make_pair(in_dev, out_dev); | ||||
|       }; | ||||
|   DeviceInferenceFunctionType device_inference_function_; | ||||
|  | ||||
|   std::function<std::vector<TensorFiller>( | ||||
|       const std::vector<std::vector<int64_t>>&)> | ||||
|  | ||||
| @ -88,7 +88,7 @@ class Int8AddOp final : public Operator<CPUContext> { | ||||
|         setupStatus == qnnp_status_success, | ||||
|         "failed to setup QNNPACK add operator"); | ||||
|  | ||||
| #ifdef FBCODE_CAFFE2 | ||||
| #if defined(FBCODE_CAFFE2) || !defined(USE_INTERNAL_PTHREADPOOL_IMPL) | ||||
|     const qnnp_status runStatus = | ||||
|         qnnp_run_operator(this->qnnpackOperator_, nullptr /* thread pool */); | ||||
| #else | ||||
|  | ||||
| @ -80,7 +80,7 @@ class Int8AveragePoolOp final : public ConvPoolOpBase<CPUContext> { | ||||
|           setupStatus == qnnp_status_success, | ||||
|           "failed to setup QNNPACK Global Average Pooling operator"); | ||||
|  | ||||
| #ifdef FBCODE_CAFFE2 | ||||
| #if defined(FBCODE_CAFFE2) || !defined(USE_INTERNAL_PTHREADPOOL_IMPL) | ||||
|       const qnnp_status runStatus = | ||||
|           qnnp_run_operator(this->qnnpackGlobalOperator_, | ||||
|             nullptr /* thread pool */); | ||||
| @ -122,7 +122,7 @@ class Int8AveragePoolOp final : public ConvPoolOpBase<CPUContext> { | ||||
|           setupStatus == qnnp_status_success, | ||||
|           "failed to setup QNNPACK Average Pooling operator"); | ||||
|  | ||||
| #ifdef FBCODE_CAFFE2 | ||||
| #if defined(FBCODE_CAFFE2) || !defined(USE_INTERNAL_PTHREADPOOL_IMPL) | ||||
|       const qnnp_status runStatus = | ||||
|           qnnp_run_operator(this->qnnpackOperator_, nullptr /* thread pool */); | ||||
| #else | ||||
|  | ||||
| @ -72,7 +72,7 @@ class Int8ChannelShuffleOp final : public ConvPoolOpBase<CPUContext> { | ||||
|         setupStatus == qnnp_status_success, | ||||
|         "failed to setup QNNPACK channel shuffle operator"); | ||||
|  | ||||
| #ifdef FBCODE_CAFFE2 | ||||
| #if defined(FBCODE_CAFFE2) || !defined(USE_INTERNAL_PTHREADPOOL_IMPL) | ||||
|     const qnnp_status runStatus = | ||||
|         qnnp_run_operator(this->qnnpackOperator_, nullptr /* thread pool */); | ||||
| #else | ||||
|  | ||||
| @ -141,7 +141,7 @@ class Int8ConvOp final : public ConvPoolOpBase<CPUContext> { | ||||
|         lastOutputPointer_ = Y->t.template mutable_data<uint8_t>(); | ||||
|       } | ||||
|  | ||||
| #ifdef FBCODE_CAFFE2 | ||||
| #if defined(FBCODE_CAFFE2) || !defined(USE_INTERNAL_PTHREADPOOL_IMPL) | ||||
|       const qnnp_status runStatus = | ||||
|           qnnp_run_operator(this->qnnpackObject_, nullptr /* thread pool */); | ||||
| #else | ||||
|  | ||||
| @ -140,7 +140,7 @@ class Int8ConvTransposeOp final : public ConvTransposeUnpoolBase<CPUContext> { | ||||
|         lastOutputPointer_ = Y->t.template mutable_data<uint8_t>(); | ||||
|       } | ||||
|  | ||||
| #ifdef FBCODE_CAFFE2 | ||||
| #if defined(FBCODE_CAFFE2) || !defined(USE_INTERNAL_PTHREADPOOL_IMPL) | ||||
|       const qnnp_status runStatus = | ||||
|           qnnp_run_operator(this->qnnpackObject_, nullptr /* thread pool */); | ||||
| #else | ||||
|  | ||||
| @ -104,7 +104,7 @@ class Int8FCOp final : public Operator<CPUContext> { | ||||
|         lastOutputPointer_ = Y->t.template mutable_data<uint8_t>(); | ||||
|       } | ||||
|  | ||||
| #ifdef FBCODE_CAFFE2 | ||||
| #if defined(FBCODE_CAFFE2) || !defined(USE_INTERNAL_PTHREADPOOL_IMPL) | ||||
|       const qnnp_status runStatus = | ||||
|           qnnp_run_operator(this->qnnpackObject_, nullptr /* thread pool */); | ||||
| #else | ||||
|  | ||||
| @ -80,7 +80,7 @@ class Int8LeakyReluOp final : public Operator<CPUContext> { | ||||
|         setupStatus == qnnp_status_success, | ||||
|         "failed to setup QNNPACK Leaky ReLU operator"); | ||||
|  | ||||
| #ifdef FBCODE_CAFFE2 | ||||
| #if defined(FBCODE_CAFFE2) || !defined(USE_INTERNAL_PTHREADPOOL_IMPL) | ||||
|     const qnnp_status runStatus = | ||||
|         qnnp_run_operator(this->qnnpackOperator_, nullptr /* thread pool */); | ||||
| #else | ||||
|  | ||||
| @ -74,7 +74,7 @@ class Int8MaxPoolOp final : public ConvPoolOpBase<CPUContext> { | ||||
|         setupStatus == qnnp_status_success, | ||||
|         "failed to setup QNNPACK Max Pooling operator"); | ||||
|  | ||||
| #ifdef FBCODE_CAFFE2 | ||||
| #if defined(FBCODE_CAFFE2) || !defined(USE_INTERNAL_PTHREADPOOL_IMPL) | ||||
|     const qnnp_status runStatus = | ||||
|         qnnp_run_operator(this->qnnpackOperator_, nullptr /* thread pool */); | ||||
| #else | ||||
|  | ||||
| @ -65,7 +65,7 @@ class Int8ReluOp final : public Operator<CPUContext> { | ||||
|         setupStatus == qnnp_status_success, | ||||
|         "failed to setup QNNPACK Clamp operator"); | ||||
|  | ||||
| #ifdef FBCODE_CAFFE2 | ||||
| #if defined(FBCODE_CAFFE2) || !defined(USE_INTERNAL_PTHREADPOOL_IMPL) | ||||
|     const qnnp_status runStatus = | ||||
|         qnnp_run_operator(this->qnnpackOperator_, nullptr /* thread pool */); | ||||
| #else | ||||
|  | ||||
| @ -73,7 +73,7 @@ class Int8SigmoidOp final : public Operator<CPUContext> { | ||||
|         setupStatus == qnnp_status_success, | ||||
|         "failed to setup QNNPACK Sigmoid operator"); | ||||
|  | ||||
| #ifdef FBCODE_CAFFE2 | ||||
| #if defined(FBCODE_CAFFE2) || !defined(USE_INTERNAL_PTHREADPOOL_IMPL) | ||||
|     const qnnp_status runStatus = | ||||
|         qnnp_run_operator(this->qnnpackOperator_, nullptr /* thread pool */); | ||||
| #else | ||||
|  | ||||
| @ -73,7 +73,7 @@ class Int8SoftmaxOp final : public Operator<CPUContext> { | ||||
|         setupStatus == qnnp_status_success, | ||||
|         "failed to setup QNNPACK SoftArgMax operator"); | ||||
|  | ||||
| #ifdef FBCODE_CAFFE2 | ||||
| #if defined(FBCODE_CAFFE2) || !defined(USE_INTERNAL_PTHREADPOOL_IMPL) | ||||
|     const qnnp_status runStatus = | ||||
|         qnnp_run_operator(this->qnnpackOperator_, nullptr /* thread pool */); | ||||
| #else | ||||
|  | ||||
| @ -42,13 +42,48 @@ if platform.system() == 'Windows': | ||||
|     else: | ||||
|         cuda_path = '' | ||||
|  | ||||
|     if not is_conda and sys.version_info >= (3, 8): | ||||
|         dll_paths = list(filter(os.path.exists, [th_dll_path, py_dll_path, nvtoolsext_dll_path, cuda_path])) | ||||
|     import ctypes | ||||
|     kernel32 = ctypes.WinDLL('kernel32.dll', use_last_error=True) | ||||
|     dll_paths = list(filter(os.path.exists, [th_dll_path, py_dll_path, nvtoolsext_dll_path, cuda_path])) | ||||
|     with_load_library_flags = hasattr(kernel32, 'AddDllDirectory') | ||||
|     prev_error_mode = kernel32.SetErrorMode(0x0001) | ||||
|  | ||||
|         for dll_path in dll_paths: | ||||
|     kernel32.LoadLibraryW.restype = ctypes.c_void_p | ||||
|     if with_load_library_flags: | ||||
|         kernel32.AddDllDirectory.restype = ctypes.c_void_p | ||||
|         kernel32.LoadLibraryExW.restype = ctypes.c_void_p | ||||
|  | ||||
|     for dll_path in dll_paths: | ||||
|         if sys.version_info >= (3, 8): | ||||
|             os.add_dll_directory(dll_path) | ||||
|     else: | ||||
|         dll_paths = [th_dll_path, py_dll_path, nvtoolsext_dll_path, cuda_path] | ||||
|         dll_paths = list(filter(os.path.exists, dll_paths)) + [os.environ['PATH']] | ||||
|         elif with_load_library_flags: | ||||
|             res = kernel32.AddDllDirectory(dll_path) | ||||
|             if res is None: | ||||
|                 err = ctypes.WinError(ctypes.get_last_error()) | ||||
|                 err.strerror += ' Error adding "{}" to the DLL directories.'.format(dll_path) | ||||
|                 raise err | ||||
|  | ||||
|         os.environ['PATH'] = ';'.join(dll_paths) | ||||
|     dlls = glob.glob(os.path.join(th_dll_path, '*.dll')) | ||||
|     path_patched = False | ||||
|     for dll in dlls: | ||||
|         is_loaded = False | ||||
|         if with_load_library_flags: | ||||
|             res = kernel32.LoadLibraryExW(dll, None, 0x00001100) | ||||
|             last_error = ctypes.get_last_error() | ||||
|             if res is None and last_error != 126: | ||||
|                 err = ctypes.WinError(last_error) | ||||
|                 err.strerror += ' Error loading "{}" or one of its dependencies.'.format(dll) | ||||
|                 raise err | ||||
|             elif res is not None: | ||||
|                 is_loaded = True | ||||
|         if not is_loaded: | ||||
|             if not path_patched: | ||||
|                 os.environ['PATH'] = ';'.join(dll_paths + [os.environ['PATH']]) | ||||
|                 path_patched = True | ||||
|             res = kernel32.LoadLibraryW(dll) | ||||
|             if res is None: | ||||
|                 err = ctypes.WinError(ctypes.get_last_error()) | ||||
|                 err.strerror += ' Error loading "{}" or one of its dependencies.'.format(dll) | ||||
|                 raise err | ||||
|  | ||||
|     kernel32.SetErrorMode(prev_error_mode) | ||||
|  | ||||
| @ -4,6 +4,7 @@ | ||||
| #include <istream> | ||||
| #include <ostream> | ||||
| #include <fstream> | ||||
| #include <algorithm> | ||||
|  | ||||
| #include <c10/core/Allocator.h> | ||||
| #include <c10/core/Backend.h> | ||||
| @ -303,10 +304,10 @@ void PyTorchStreamWriter::setup(const string& file_name) { | ||||
|  | ||||
|   mz_zip_writer_init_v2(ar_.get(), 0, MZ_ZIP_FLAG_WRITE_ZIP64); | ||||
|   valid("initializing archive ", file_name.c_str()); | ||||
| } | ||||
|  | ||||
|   std::string version = c10::to_string(kProducedFileFormatVersion); | ||||
|   version.push_back('\n'); | ||||
|   writeRecord("version", version.c_str(), version.size()); | ||||
| void PyTorchStreamWriter::setMinVersion(const uint64_t version) { | ||||
|   version_ = std::max(version, version_); | ||||
| } | ||||
|  | ||||
| void PyTorchStreamWriter::writeRecord( | ||||
| @ -339,6 +340,11 @@ void PyTorchStreamWriter::writeRecord( | ||||
| } | ||||
|  | ||||
| void PyTorchStreamWriter::writeEndOfFile() { | ||||
|   // Writes version info | ||||
|   std::string version = c10::to_string(version_); | ||||
|   version.push_back('\n'); | ||||
|   writeRecord("version", version.c_str(), version.size()); | ||||
|  | ||||
|   AT_ASSERT(!finalized_); | ||||
|   finalized_ = true; | ||||
|   mz_zip_writer_finalize_archive(ar_.get()); | ||||
|  | ||||
| @ -94,14 +94,45 @@ constexpr uint64_t kMinSupportedFileFormatVersion = 0x1L; | ||||
| constexpr uint64_t kMaxSupportedFileFormatVersion = 0x5L; | ||||
|  | ||||
| // Versions (i.e. why was the version number bumped?) | ||||
|  | ||||
| // Note [Dynamic Versions and torch.jit.save vs. torch.save] | ||||
| // | ||||
| // Our versioning scheme has a "produced file format version" which | ||||
| // describes how an archive is to be read. The version written in an archive | ||||
| // is at least this current produced file format version, but may be greater | ||||
| // if it includes certain symbols. We refer to these conditional versions | ||||
| // as "dynamic," since they are identified at runtime. | ||||
| // | ||||
| // Dynamic versioning is useful when an operator's semantics are updated. | ||||
| // When using torch.jit.save we want those semantics to be preserved. If | ||||
| // we bumped the produced file format version on every change, however, | ||||
| // then older versions of PyTorch couldn't read even simple archives, like | ||||
| // a single tensor, from newer versions of PyTorch. Instead, we | ||||
| // assign dynamic versions to these changes that override the | ||||
| // produced file format version as needed. That is, when the semantics | ||||
| // of torch.div changed it was assigned dynamic version 4, and when | ||||
| // torch.jit.saving modules that use torch.div those archives also have | ||||
| // (at least) version 4. This prevents earlier versions of PyTorch | ||||
| // from accidentally performing the wrong kind of division. Modules | ||||
| // that don't use torch.div or other operators with dynamic versions | ||||
| // can write the produced file format version, and these programs will | ||||
| // run as expected on earlier versions of PyTorch. | ||||
| // | ||||
| // While torch.jit.save attempts to preserve operator semantics, | ||||
| // torch.save does not. torch.save is analogous to pickling Python, so | ||||
| // a function that uses torch.div will have different behavior if torch.saved | ||||
| // and torch.loaded across PyTorch versions. From a technical perspective, | ||||
| // torch.save ignores dynamic versioning. | ||||
|  | ||||
| // 1. Initial version | ||||
| // 2. Removed op_version_set version numbers | ||||
| // 3. Added type tags to pickle serialization of container types | ||||
| // 4. Stopped integer division using torch.div | ||||
| // 4. (Dynamic) Stopped integer division using torch.div | ||||
| //      (a versioned symbol preserves the historic behavior of versions 1--3) | ||||
| // 5. (Read-only) Stops torch.full inferring a floating point dtype | ||||
| //      when given integer fill values. | ||||
| constexpr uint64_t kProducedFileFormatVersion = 0x4L; | ||||
| // 5. (Dynamic) Stops torch.full inferring a floating point dtype | ||||
| //      when given bool or integer fill values. | ||||
| //      (a versioned symbol preserves the historic behavior of versions 1--4) | ||||
| constexpr uint64_t kProducedFileFormatVersion = 0x3L; | ||||
|  | ||||
| // Writer-specific constants | ||||
| constexpr uint64_t kFieldAlignment = 64; | ||||
| @ -144,6 +175,8 @@ class CAFFE2_API PyTorchStreamWriter final { | ||||
|   explicit PyTorchStreamWriter( | ||||
|       const std::function<size_t(const void*, size_t)>& writer_func); | ||||
|  | ||||
|    void setMinVersion(const uint64_t version); | ||||
|  | ||||
|   void writeRecord( | ||||
|       const std::string& name, | ||||
|       const void* data, | ||||
| @ -171,6 +204,7 @@ class CAFFE2_API PyTorchStreamWriter final { | ||||
|   std::string padding_; | ||||
|   std::ofstream file_stream_; | ||||
|   std::function<size_t(const void*, size_t)> writer_func_; | ||||
|   uint64_t version_ = kProducedFileFormatVersion; | ||||
|   bool finalized_ = false; | ||||
|   bool err_seen_ = false; | ||||
|   friend size_t ostream_write_func( | ||||
|  | ||||
| @ -195,7 +195,12 @@ bool NNPACKConvOp::RunOnDeviceWithOrderNCHW() { | ||||
|   const nnp_size output_subsample = {.width = static_cast<size_t>(stride_w()), | ||||
|                                      .height = static_cast<size_t>(stride_h())}; | ||||
|   initNNPACK(); | ||||
|  | ||||
| #if !defined(USE_INTERNAL_PTHREADPOOL_IMPL) | ||||
|   pthreadpool_t pool = nullptr; | ||||
| #else | ||||
|   pthreadpool_t pool = reinterpret_cast<pthreadpool_t>(ws_->GetThreadPool()); | ||||
| #endif | ||||
|  | ||||
|   runWithSharedBuffer<CPUContext>(ws_, [&](Tensor* buffer) { | ||||
|     if (transformStrategy_ == nnp_convolution_transform_strategy_precompute) { | ||||
|  | ||||
| @ -1,15 +1,8 @@ | ||||
| # TODO: Add ThreadPoolXNNPACK.cc when XNNPACK integration is updated | ||||
| # to pass the actual threadpool ptr instead of nullptr. | ||||
| if(INTERN_BUILD_MOBILE AND NOT BUILD_CAFFE2_MOBILE) | ||||
|   add_definitions(-DUSE_INTERNAL_THREADPOOL_IMPL) | ||||
|   list(APPEND Caffe2_CPU_SRCS | ||||
|     utils/string_utils.cc | ||||
|     utils/threadpool/pthreadpool.cc | ||||
|     utils/threadpool/pthreadpool_impl.cc | ||||
|     utils/threadpool/pthreadpool_new_if_impl.c | ||||
|     utils/threadpool/pthreadpool-cpp.cc | ||||
|     utils/threadpool/ThreadPool.cc | ||||
|     utils/threadpool/ThreadPoolMobile.cc | ||||
|     utils/threadpool/ThreadPoolXNNPACK.cc | ||||
|   ) | ||||
|   set(Caffe2_CPU_SRCS ${Caffe2_CPU_SRCS} PARENT_SCOPE) | ||||
|   return() | ||||
| @ -28,23 +21,19 @@ list(APPEND Caffe2_CPU_SRCS | ||||
|   utils/proto_convert.cc | ||||
|   utils/proto_utils.cc | ||||
|   utils/proto_wrap.cc | ||||
|   utils/threadpool/ThreadPool.cc | ||||
|   utils/signal_handler.cc | ||||
|   utils/smart_tensor_printer.cc | ||||
|   utils/string_utils.cc | ||||
|   utils/threadpool/ThreadPool.cc) | ||||
|   utils/string_utils.cc) | ||||
|  | ||||
| # ---[ threadpool/pthreadpool* is a local modification of the NNPACK | ||||
| # pthreadpool with a very similar interface. Neither NNPACK, nor this | ||||
| # thread pool supports Windows. | ||||
| if(NOT MSVC AND USE_XNNPACK) | ||||
|   add_definitions(-DUSE_INTERNAL_THREADPOOL_IMPL) | ||||
|   set(Caffe2_CPU_SRCS ${Caffe2_CPU_SRCS} | ||||
|           utils/threadpool/pthreadpool.cc | ||||
|           utils/threadpool/pthreadpool_impl.cc | ||||
|           utils/threadpool/pthreadpool_new_if_impl.c | ||||
|           utils/threadpool/ThreadPoolMobile.cc | ||||
|           utils/threadpool/ThreadPoolXNNPACK.cc | ||||
|           ) | ||||
| if(USE_PTHREADPOOL) | ||||
|   list(APPEND Caffe2_CPU_SRCS | ||||
|     utils/threadpool/pthreadpool-cpp.cc) | ||||
|   if(USE_INTERNAL_PTHREADPOOL_IMPL) | ||||
|     list(APPEND Caffe2_CPU_SRCS | ||||
|       utils/threadpool/pthreadpool.cc | ||||
|       utils/threadpool/pthreadpool_impl.cc) | ||||
|   endif() | ||||
| endif() | ||||
|  | ||||
| set(Caffe2_GPU_SRCS ${Caffe2_GPU_SRCS} | ||||
|  | ||||
| @ -1,21 +0,0 @@ | ||||
| #include <caffe2/utils/threadpool/ThreadPoolMobile.h> | ||||
| #include <caffe2/utils/threadpool/ThreadPool.h> | ||||
| #include <caffe2/utils/threadpool/pthreadpool.h> | ||||
|  | ||||
| namespace caffe2 { | ||||
|  | ||||
| caffe2::ThreadPool* mobile_threadpool() { | ||||
| #ifdef C10_MOBILE | ||||
|   static std::unique_ptr<caffe2::ThreadPool> thread_pool = | ||||
|       caffe2::ThreadPool::defaultThreadPool(); | ||||
|   return thread_pool.get(); | ||||
| #else | ||||
|   return nullptr; | ||||
| #endif | ||||
| } | ||||
|  | ||||
| pthreadpool_t mobile_pthreadpool() { | ||||
|   return reinterpret_cast<pthreadpool_t>(mobile_threadpool()); | ||||
| } | ||||
|  | ||||
| } // namespace caffe2 | ||||
| @ -1,24 +0,0 @@ | ||||
| #pragma once | ||||
| #include <caffe2/utils/threadpool/pthreadpool.h> | ||||
|  | ||||
| // TODO Implement a parallel_for version for Mobile here, add to Aten/Parallel.h | ||||
|  | ||||
| namespace caffe2 { | ||||
|  | ||||
| class ThreadPool; | ||||
|  | ||||
| // Return a singleton instance of caffe2::ThreadPool for ATen/TH multithreading. | ||||
| ThreadPool* mobile_threadpool(); | ||||
|  | ||||
| // NOTE: This interface is temporary and should not be used. | ||||
| // Please use Aten/Parallel.h for parallel primitives in pytorch. | ||||
| // This implementation will be used by pytorch mobile, specifically | ||||
| // NNPACK/QNNPACK. For mobile we need to use caffe2::ThreadPool instead of the | ||||
| // 3rd party pthreadpool. Future work (TODO) Implement a mobile version of | ||||
| // "at::parallel_for" using caffe2::ThreadPool so all ATen/TH multithreading | ||||
| // usage is mobile friendly; Refactor QNNPACK or pthreadpool to explicitly using | ||||
| // "at::parallel_for" primitive to replace pthreadpool_compute_1d for Pytorch; | ||||
| pthreadpool_t mobile_pthreadpool(); | ||||
|  | ||||
| size_t getDefaultNumThreads(); | ||||
| } // namespace caffe2 | ||||
| @ -1,22 +0,0 @@ | ||||
| #include <caffe2/utils/threadpool/pthreadpool.h> | ||||
| #include <caffe2/utils/threadpool/ThreadPoolMobile.h> | ||||
| #include <caffe2/utils/threadpool/ThreadPoolXNNPACK.h> | ||||
| #include <memory> | ||||
|  | ||||
| namespace caffe2 { | ||||
|  | ||||
| // Will be unified. | ||||
| pthreadpool_t xnnpack_threadpool() { | ||||
| // Depending on internal implemenation vs. OSS we will link against pthreadpool_create_xnnpack | ||||
| // or pthreadpool_create. This is only temporary. It will be unified soon. | ||||
| #ifdef USE_INTERNAL_THREADPOOL_IMPL | ||||
|   static std::unique_ptr<pthreadpool, decltype(&pthreadpool_destroy_xnnpack)> | ||||
|       threadpool(pthreadpool_create_xnnpack(getDefaultNumThreads()), pthreadpool_destroy_xnnpack); | ||||
| #else | ||||
|   static std::unique_ptr<pthreadpool, decltype(&pthreadpool_destroy)> | ||||
|       threadpool(pthreadpool_create(getDefaultNumThreads()), pthreadpool_destroy); | ||||
| #endif | ||||
|   return threadpool.get(); | ||||
| } | ||||
|  | ||||
| } // namespace caffe2 | ||||
| @ -1,7 +0,0 @@ | ||||
| #pragma once | ||||
| // Creating a separate .h/.cc file for creating threadpool for XNNPACK | ||||
| // to avoid touching existing internal builds. | ||||
| // When we unify threadpools this should all go away. | ||||
| namespace caffe2 { | ||||
| pthreadpool_t xnnpack_threadpool(); | ||||
| } // namespace caffe2 | ||||
							
								
								
									
										71
									
								
								caffe2/utils/threadpool/pthreadpool-cpp.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								caffe2/utils/threadpool/pthreadpool-cpp.cc
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,71 @@ | ||||
| #include <caffe2/utils/threadpool/pthreadpool-cpp.h> | ||||
| #include <c10/util/Exception.h> | ||||
|  | ||||
| namespace caffe2 { | ||||
|  | ||||
| PThreadPool::PThreadPool(const size_t thread_count) | ||||
|     : threadpool_(pthreadpool_create(thread_count), pthreadpool_destroy) {} | ||||
|  | ||||
| size_t PThreadPool::get_thread_count() const { | ||||
|   std::lock_guard<std::mutex> lock{mutex_}; | ||||
|  | ||||
|   TORCH_INTERNAL_ASSERT(threadpool_.get(), "Invalid threadpool!"); | ||||
|   return pthreadpool_get_threads_count(threadpool_.get()); | ||||
| } | ||||
|  | ||||
| void PThreadPool::set_thread_count(const size_t thread_count) { | ||||
|   std::lock_guard<std::mutex> lock{mutex_}; | ||||
|  | ||||
|   // As it stands, pthreadpool is an entirely data parallel framework with no | ||||
|   // support for task parallelism.  Hence, all functions are blocking, and no | ||||
|   // user-provided tasks can be in flight when the control is returned to the | ||||
|   // user of the API, which means re-initializing the library, without the | ||||
|   // need to wait on any pending tasks, is all one needs to do to re-adjust | ||||
|   // the thread count. | ||||
|   threadpool_.reset(pthreadpool_create(thread_count)); | ||||
| } | ||||
|  | ||||
| void PThreadPool::run( | ||||
|     const std::function<void(size_t)>& fn, | ||||
|     const size_t range) { | ||||
|   std::lock_guard<std::mutex> lock{mutex_}; | ||||
|  | ||||
|   TORCH_INTERNAL_ASSERT(threadpool_.get(), "Invalid threadpool!"); | ||||
|  | ||||
|   struct Context final { | ||||
|     const std::function<void(size_t)>& fn; | ||||
|   } context{ | ||||
|       fn, | ||||
|   }; | ||||
|  | ||||
|   pthreadpool_parallelize_1d( | ||||
|       threadpool_.get(), | ||||
|       // Note: pthreadpool_parallelize_1d() is a blocking function.  The | ||||
|       // function pointer to this lambda passed on to | ||||
|       // pthreadpool_parallelize_1d() cannot go out of scope until | ||||
|       // pthreadpool_parallelize_1d() returns. | ||||
|       [](void* const context, const size_t item) { | ||||
|         reinterpret_cast<Context*>(context)->fn(item); | ||||
|       }, | ||||
|       &context, | ||||
|       range, | ||||
|       0u); | ||||
| } | ||||
|  | ||||
| // Forward declaration | ||||
| size_t getDefaultNumThreads(); | ||||
|  | ||||
| PThreadPool* pthreadpool() { | ||||
|   static std::unique_ptr<PThreadPool> threadpool = | ||||
|       std::make_unique<PThreadPool>(getDefaultNumThreads()); | ||||
|   return threadpool.get(); | ||||
| } | ||||
|  | ||||
| pthreadpool_t pthreadpool_() { | ||||
|   PThreadPool* const threadpool = pthreadpool(); | ||||
|   TORCH_INTERNAL_ASSERT( | ||||
|       threadpool, "Failed to acquire an instance of PThreadPool!"); | ||||
|   return threadpool->threadpool_.get(); | ||||
| } | ||||
|  | ||||
| } // namespace caffe2 | ||||
							
								
								
									
										54
									
								
								caffe2/utils/threadpool/pthreadpool-cpp.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								caffe2/utils/threadpool/pthreadpool-cpp.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,54 @@ | ||||
| #pragma once | ||||
|  | ||||
| #ifdef USE_PTHREADPOOL | ||||
|  | ||||
| #ifdef USE_INTERNAL_PTHREADPOOL_IMPL | ||||
| #include <caffe2/utils/threadpool/pthreadpool.h> | ||||
| #else | ||||
| #include <pthreadpool.h> | ||||
| #endif | ||||
|  | ||||
| #include <functional> | ||||
| #include <memory> | ||||
| #include <mutex> | ||||
|  | ||||
| namespace caffe2 { | ||||
|  | ||||
| class PThreadPool final { | ||||
|  public: | ||||
|   explicit PThreadPool(size_t thread_count); | ||||
|   ~PThreadPool() = default; | ||||
|  | ||||
|   PThreadPool(const PThreadPool&) = delete; | ||||
|   PThreadPool& operator=(const PThreadPool&) = delete; | ||||
|  | ||||
|   PThreadPool(PThreadPool&&) = delete; | ||||
|   PThreadPool& operator=(PThreadPool&&) = delete; | ||||
|  | ||||
|   size_t get_thread_count() const; | ||||
|   void set_thread_count(size_t thread_count); | ||||
|  | ||||
|   // Run, in parallel, function fn(task_id) over task_id in range [0, range). | ||||
|   // This function is blocking.  All input is processed by the time it returns. | ||||
|   void run(const std::function<void(size_t)>& fn, size_t range); | ||||
|  | ||||
|  private: | ||||
|   friend pthreadpool_t pthreadpool_(); | ||||
|  | ||||
|  private: | ||||
|   mutable std::mutex mutex_; | ||||
|   std::unique_ptr<pthreadpool, decltype(&pthreadpool_destroy)> threadpool_; | ||||
| }; | ||||
|  | ||||
| // Return a singleton instance of PThreadPool for ATen/TH multithreading. | ||||
| PThreadPool* pthreadpool(); | ||||
|  | ||||
| // Exposes the underlying implementation of PThreadPool. | ||||
| // Only for use in external libraries so as to unify threading across | ||||
| // internal (i.e. ATen, etc.) and external (e.g. NNPACK, QNNPACK, XNNPACK) | ||||
| // use cases. | ||||
| pthreadpool_t pthreadpool_(); | ||||
|  | ||||
| } // namespace caffe2 | ||||
|  | ||||
| #endif /* USE_PTHREADPOOL */ | ||||
| @ -32,7 +32,7 @@ static inline size_t min(size_t a, size_t b) { | ||||
| } | ||||
|  | ||||
| struct compute_1d_tiled_context { | ||||
|   pthreadpool_function_1d_tiled_t function; | ||||
|   legacy_pthreadpool_function_1d_tiled_t function; | ||||
|   void* argument; | ||||
|   size_t range; | ||||
|   size_t tile; | ||||
| @ -46,9 +46,9 @@ static void compute_1d_tiled(void* context_, size_t linear_index) { | ||||
|   context->function(context->argument, index, tile); | ||||
| } | ||||
|  | ||||
| void pthreadpool_compute_1d_tiled( | ||||
|   pthreadpool_t threadpool, | ||||
|   pthreadpool_function_1d_tiled_t function, | ||||
| void legacy_pthreadpool_compute_1d_tiled( | ||||
|   legacy_pthreadpool_t threadpool, | ||||
|   legacy_pthreadpool_function_1d_tiled_t function, | ||||
|   void* argument, | ||||
|   size_t range, | ||||
|   size_t tile) | ||||
| @ -65,12 +65,12 @@ void pthreadpool_compute_1d_tiled( | ||||
|                                                /*.argument = */ argument, | ||||
|                                                /*.range = */ range, | ||||
|                                                /*.tile = */ tile}; | ||||
|     pthreadpool_compute_1d(threadpool, (pthreadpool_function_1d_t) compute_1d_tiled, &context, tile_range); | ||||
|     legacy_pthreadpool_compute_1d(threadpool, (legacy_pthreadpool_function_1d_t) compute_1d_tiled, &context, tile_range); | ||||
|   } | ||||
| } | ||||
|  | ||||
| struct compute_2d_context { | ||||
|   pthreadpool_function_2d_t function; | ||||
|   legacy_pthreadpool_function_2d_t function; | ||||
|   void* argument; | ||||
|   caffe2::FixedDivisor<int32_t> range_j; | ||||
| }; | ||||
| @ -85,9 +85,9 @@ static void compute_2d(void* context_, size_t linear_index) { | ||||
|   context->function(context->argument, q, r); | ||||
| } | ||||
|  | ||||
| void pthreadpool_compute_2d( | ||||
|   struct pthreadpool* threadpool, | ||||
|   pthreadpool_function_2d_t function, | ||||
| void legacy_pthreadpool_compute_2d( | ||||
|   legacy_pthreadpool_t threadpool, | ||||
|   legacy_pthreadpool_function_2d_t function, | ||||
|   void* argument, | ||||
|   size_t range_i, | ||||
|   size_t range_j) | ||||
| @ -106,12 +106,12 @@ void pthreadpool_compute_2d( | ||||
|         /*.function = */ function, | ||||
|         /*.argument = */ argument, | ||||
|         /*.range_j = */ caffe2::FixedDivisor<int32_t>(range_j)}; | ||||
|     pthreadpool_compute_1d(threadpool, (pthreadpool_function_1d_t) compute_2d, &context, range_i * range_j); | ||||
|     legacy_pthreadpool_compute_1d(threadpool, (legacy_pthreadpool_function_1d_t) compute_2d, &context, range_i * range_j); | ||||
|   } | ||||
| } | ||||
|  | ||||
| struct compute_2d_tiled_context { | ||||
|   pthreadpool_function_2d_tiled_t function; | ||||
|   legacy_pthreadpool_function_2d_tiled_t function; | ||||
|   void* argument; | ||||
|   caffe2::FixedDivisor<int32_t> tile_range_j; | ||||
|   size_t range_i; | ||||
| @ -135,9 +135,9 @@ static void compute_2d_tiled(void* context_, size_t linear_index) { | ||||
|   context->function(context->argument, index_i, index_j, tile_i, tile_j); | ||||
| } | ||||
|  | ||||
| void pthreadpool_compute_2d_tiled( | ||||
|   pthreadpool_t threadpool, | ||||
|   pthreadpool_function_2d_tiled_t function, | ||||
| void legacy_pthreadpool_compute_2d_tiled( | ||||
|   legacy_pthreadpool_t threadpool, | ||||
|   legacy_pthreadpool_function_2d_tiled_t function, | ||||
|   void* argument, | ||||
|   size_t range_i, | ||||
|   size_t range_j, | ||||
| @ -166,12 +166,12 @@ void pthreadpool_compute_2d_tiled( | ||||
|         /*.range_j = */ range_j, | ||||
|         /*.tile_i = */ tile_i, | ||||
|         /*.tile_j = */ tile_j}; | ||||
|     pthreadpool_compute_1d(threadpool, (pthreadpool_function_1d_t) compute_2d_tiled, &context, tile_range_i * tile_range_j); | ||||
|     legacy_pthreadpool_compute_1d(threadpool, (legacy_pthreadpool_function_1d_t) compute_2d_tiled, &context, tile_range_i * tile_range_j); | ||||
|   } | ||||
| } | ||||
|  | ||||
| struct compute_3d_tiled_context { | ||||
|   pthreadpool_function_3d_tiled_t function; | ||||
|   legacy_pthreadpool_function_3d_tiled_t function; | ||||
|   void* argument; | ||||
|   caffe2::FixedDivisor<int32_t> tile_range_j; | ||||
|   caffe2::FixedDivisor<int32_t> tile_range_k; | ||||
| @ -205,9 +205,9 @@ static void compute_3d_tiled( | ||||
|       context->argument, index_i, index_j, index_k, tile_i, tile_j, tile_k); | ||||
| } | ||||
|  | ||||
| void pthreadpool_compute_3d_tiled( | ||||
|     pthreadpool_t threadpool, | ||||
|     pthreadpool_function_3d_tiled_t function, | ||||
| void legacy_pthreadpool_compute_3d_tiled( | ||||
|     legacy_pthreadpool_t threadpool, | ||||
|     legacy_pthreadpool_function_3d_tiled_t function, | ||||
|     void* argument, | ||||
|     size_t range_i, | ||||
|     size_t range_j, | ||||
| @ -251,16 +251,16 @@ void pthreadpool_compute_3d_tiled( | ||||
|         /*.tile_i = */ tile_i, | ||||
|         /*.tile_j = */ tile_j, | ||||
|         /*.tile_k = */ tile_k}; | ||||
|     pthreadpool_compute_1d( | ||||
|     legacy_pthreadpool_compute_1d( | ||||
|         threadpool, | ||||
|         (pthreadpool_function_1d_t)compute_3d_tiled, | ||||
|         (legacy_pthreadpool_function_1d_t)compute_3d_tiled, | ||||
|         &context, | ||||
|         tile_range_i * tile_range_j * tile_range_k); | ||||
|   } | ||||
| } | ||||
|  | ||||
| struct compute_4d_tiled_context { | ||||
|   pthreadpool_function_4d_tiled_t function; | ||||
|   legacy_pthreadpool_function_4d_tiled_t function; | ||||
|   void* argument; | ||||
|   caffe2::FixedDivisor<int32_t> tile_range_kl; | ||||
|   caffe2::FixedDivisor<int32_t> tile_range_j; | ||||
| @ -310,9 +310,9 @@ static void compute_4d_tiled( | ||||
|       tile_l); | ||||
| } | ||||
|  | ||||
| void pthreadpool_compute_4d_tiled( | ||||
|     pthreadpool_t threadpool, | ||||
|     pthreadpool_function_4d_tiled_t function, | ||||
| void legacy_pthreadpool_compute_4d_tiled( | ||||
|     legacy_pthreadpool_t threadpool, | ||||
|     legacy_pthreadpool_function_4d_tiled_t function, | ||||
|     void* argument, | ||||
|     size_t range_i, | ||||
|     size_t range_j, | ||||
| @ -367,9 +367,9 @@ void pthreadpool_compute_4d_tiled( | ||||
|         /*.tile_j = */ tile_j, | ||||
|         /*.tile_k = */ tile_k, | ||||
|         /*.tile_l = */ tile_l}; | ||||
|     pthreadpool_compute_1d( | ||||
|     legacy_pthreadpool_compute_1d( | ||||
|         threadpool, | ||||
|         (pthreadpool_function_1d_t)compute_4d_tiled, | ||||
|         (legacy_pthreadpool_function_1d_t)compute_4d_tiled, | ||||
|         &context, | ||||
|         tile_range_i * tile_range_j * tile_range_k * tile_range_l); | ||||
|   } | ||||
|  | ||||
| @ -5,49 +5,16 @@ | ||||
|  | ||||
| #include "ThreadPoolCommon.h" | ||||
|  | ||||
|  | ||||
| #include <stddef.h> // for size_t | ||||
|  | ||||
| typedef struct pthreadpool* pthreadpool_t; | ||||
|  | ||||
| typedef void (*pthreadpool_function_1d_t)(void*, size_t); | ||||
| typedef void (*pthreadpool_function_1d_tiled_t)(void*, size_t, size_t); | ||||
| typedef void (*pthreadpool_function_2d_t)(void*, size_t, size_t); | ||||
| typedef void (*pthreadpool_function_2d_tiled_t)(void*, size_t, size_t, size_t, size_t); | ||||
| typedef void (*pthreadpool_function_3d_tiled_t)( | ||||
|     void*, | ||||
|     size_t, | ||||
|     size_t, | ||||
|     size_t, | ||||
|     size_t, | ||||
|     size_t, | ||||
|     size_t); | ||||
| typedef void (*pthreadpool_function_4d_tiled_t)( | ||||
|     void*, | ||||
|     size_t, | ||||
|     size_t, | ||||
|     size_t, | ||||
|     size_t, | ||||
|     size_t, | ||||
|     size_t, | ||||
|     size_t, | ||||
|     size_t); | ||||
|  | ||||
| #include <stdint.h> // for uint32_t | ||||
|  | ||||
| typedef void (*pthreadpool_task_1d_t)(void*, size_t); | ||||
| typedef void (*pthreadpool_task_1d_tile_1d_t)(void*, size_t, size_t); | ||||
| typedef void (*pthreadpool_task_2d_t)(void*, size_t, size_t); | ||||
| typedef void (*pthreadpool_task_2d_tile_1d_t)(void*, size_t, size_t, size_t); | ||||
| typedef void (*pthreadpool_task_2d_tile_2d_t)(void*, size_t, size_t, size_t, size_t); | ||||
| typedef void (*pthreadpool_task_3d_tile_2d_t)( | ||||
|     void*, | ||||
|     size_t, | ||||
|     size_t, | ||||
|     size_t, | ||||
|     size_t, | ||||
|     size_t); | ||||
| typedef void (*pthreadpool_task_4d_tile_2d_t)( | ||||
| typedef struct pthreadpool* legacy_pthreadpool_t; | ||||
|  | ||||
| typedef void (*legacy_pthreadpool_function_1d_t)(void*, size_t); | ||||
| typedef void (*legacy_pthreadpool_function_1d_tiled_t)(void*, size_t, size_t); | ||||
| typedef void (*legacy_pthreadpool_function_2d_t)(void*, size_t, size_t); | ||||
| typedef void (*legacy_pthreadpool_function_2d_tiled_t)(void*, size_t, size_t, size_t, size_t); | ||||
| typedef void (*legacy_pthreadpool_function_3d_tiled_t)( | ||||
|     void*, | ||||
|     size_t, | ||||
|     size_t, | ||||
| @ -55,16 +22,7 @@ typedef void (*pthreadpool_task_4d_tile_2d_t)( | ||||
|     size_t, | ||||
|     size_t, | ||||
|     size_t); | ||||
| typedef void (*pthreadpool_task_5d_tile_2d_t)( | ||||
|     void*, | ||||
|     size_t, | ||||
|     size_t, | ||||
|     size_t, | ||||
|     size_t, | ||||
|     size_t, | ||||
|     size_t, | ||||
|     size_t); | ||||
| typedef void (*pthreadpool_task_6d_tile_2d_t)( | ||||
| typedef void (*legacy_pthreadpool_function_4d_tiled_t)( | ||||
|     void*, | ||||
|     size_t, | ||||
|     size_t, | ||||
| @ -90,8 +48,8 @@ extern "C" { | ||||
|  *    On error the function returns NULL and sets errno accordingly. | ||||
|  */ | ||||
|  | ||||
| //Returns internal threadpool impl. | ||||
| pthreadpool_t pthreadpool_create(size_t threads_count); | ||||
| // Returns internal threadpool impl. | ||||
| legacy_pthreadpool_t legacy_pthreadpool_create(size_t threads_count); | ||||
|  | ||||
| /** | ||||
|  * Queries the number of threads in a thread pool. | ||||
| @ -100,7 +58,7 @@ pthreadpool_t pthreadpool_create(size_t threads_count); | ||||
|  * | ||||
|  * @returns  The number of threads in the thread pool. | ||||
|  */ | ||||
| size_t pthreadpool_get_threads_count(pthreadpool_t threadpool); | ||||
| size_t legacy_pthreadpool_get_threads_count(legacy_pthreadpool_t threadpool); | ||||
|  | ||||
| /** | ||||
|  * Processes items in parallel using threads from a thread pool. | ||||
| @ -117,38 +75,45 @@ size_t pthreadpool_get_threads_count(pthreadpool_t threadpool); | ||||
|  * @param[in]  items       The number of items to process. The @a function | ||||
|  *    will be called once for each item. | ||||
|  */ | ||||
| void pthreadpool_compute_1d( | ||||
|     pthreadpool_t threadpool, | ||||
|     pthreadpool_function_1d_t function, | ||||
| void legacy_pthreadpool_compute_1d( | ||||
|     legacy_pthreadpool_t threadpool, | ||||
|     legacy_pthreadpool_function_1d_t function, | ||||
|     void* argument, | ||||
|     size_t range); | ||||
|  | ||||
| void pthreadpool_compute_1d_tiled( | ||||
|     pthreadpool_t threadpool, | ||||
|     pthreadpool_function_1d_tiled_t function, | ||||
| void legacy_pthreadpool_parallelize_1d( | ||||
|     legacy_pthreadpool_t threadpool, | ||||
|     legacy_pthreadpool_function_1d_t function, | ||||
|     void* argument, | ||||
|     size_t range, | ||||
|     uint32_t flags); | ||||
|  | ||||
| void legacy_pthreadpool_compute_1d_tiled( | ||||
|     legacy_pthreadpool_t threadpool, | ||||
|     legacy_pthreadpool_function_1d_tiled_t function, | ||||
|     void* argument, | ||||
|     size_t range, | ||||
|     size_t tile); | ||||
|  | ||||
| void pthreadpool_compute_2d( | ||||
|     pthreadpool_t threadpool, | ||||
|     pthreadpool_function_2d_t function, | ||||
| void legacy_pthreadpool_compute_2d( | ||||
|     legacy_pthreadpool_t threadpool, | ||||
|     legacy_pthreadpool_function_2d_t function, | ||||
|     void* argument, | ||||
|     size_t range_i, | ||||
|     size_t range_j); | ||||
|  | ||||
| void pthreadpool_compute_2d_tiled( | ||||
|     pthreadpool_t threadpool, | ||||
|     pthreadpool_function_2d_tiled_t function, | ||||
| void legacy_pthreadpool_compute_2d_tiled( | ||||
|     legacy_pthreadpool_t threadpool, | ||||
|     legacy_pthreadpool_function_2d_tiled_t function, | ||||
|     void* argument, | ||||
|     size_t range_i, | ||||
|     size_t range_j, | ||||
|     size_t tile_i, | ||||
|     size_t tile_j); | ||||
|  | ||||
| void pthreadpool_compute_3d_tiled( | ||||
|     pthreadpool_t threadpool, | ||||
|     pthreadpool_function_3d_tiled_t function, | ||||
| void legacy_pthreadpool_compute_3d_tiled( | ||||
|     legacy_pthreadpool_t threadpool, | ||||
|     legacy_pthreadpool_function_3d_tiled_t function, | ||||
|     void* argument, | ||||
|     size_t range_i, | ||||
|     size_t range_j, | ||||
| @ -157,9 +122,9 @@ void pthreadpool_compute_3d_tiled( | ||||
|     size_t tile_j, | ||||
|     size_t tile_k); | ||||
|  | ||||
| void pthreadpool_compute_4d_tiled( | ||||
|     pthreadpool_t threadpool, | ||||
|     pthreadpool_function_4d_tiled_t function, | ||||
| void legacy_pthreadpool_compute_4d_tiled( | ||||
|     legacy_pthreadpool_t threadpool, | ||||
|     legacy_pthreadpool_function_4d_tiled_t function, | ||||
|     void* argument, | ||||
|     size_t range_i, | ||||
|     size_t range_j, | ||||
| @ -178,129 +143,29 @@ void pthreadpool_compute_4d_tiled( | ||||
|  * | ||||
|  * @param[in,out]  threadpool  The thread pool to destroy. | ||||
|  */ | ||||
| void pthreadpool_destroy(pthreadpool_t threadpool); | ||||
| void legacy_pthreadpool_destroy(legacy_pthreadpool_t threadpool); | ||||
|  | ||||
| // New interface copy/pasted from pthreadpool. | ||||
| // We will merge the internal and third-party/pthreadpool eventually. | ||||
| // For now copy-paste to get past build issues. | ||||
| #ifdef USE_INTERNAL_PTHREADPOOL_IMPL | ||||
|  | ||||
| #define PTHREADPOOL_FLAG_DISABLE_DENORMALS 0x00000001 | ||||
| #define pthreadpool_t legacy_pthreadpool_t | ||||
| #define pthreadpool_function_1d_t legacy_pthreadpool_function_1d_t | ||||
| #define pthreadpool_function_1d_tiled_t legacy_pthreadpool_function_1d_tiled_t | ||||
| #define pthreadpool_function_2d_t legacy_pthreadpool_function_2d_t | ||||
| #define pthreadpool_function_2d_tiled_t legacy_pthreadpool_function_2d_tiled_t | ||||
| #define pthreadpool_function_3d_tiled_t legacy_pthreadpool_function_3d_tiled_t | ||||
| #define pthreadpool_function_4d_tiled_t legacy_pthreadpool_function_4d_tiled_t | ||||
| #define pthreadpool_create legacy_pthreadpool_create | ||||
| #define pthreadpool_destroy legacy_pthreadpool_destroy | ||||
| #define pthreadpool_get_threads_count legacy_pthreadpool_get_threads_count | ||||
| #define pthreadpool_compute_1d legacy_pthreadpool_compute_1d | ||||
| #define pthreadpool_parallelize_1d legacy_pthreadpool_parallelize_1d | ||||
| #define pthreadpool_compute_1d_tiled legacy_pthreadpool_compute_1d_tiled | ||||
| #define pthreadpool_compute_2d legacy_pthreadpool_compute_2d | ||||
| #define pthreadpool_compute_2d_tiled legacy_pthreadpool_compute_2d_tiled | ||||
| #define pthreadpool_compute_3d_tiled legacy_pthreadpool_compute_3d_tiled | ||||
| #define pthreadpool_compute_4d_tiled legacy_pthreadpool_compute_4d_tiled | ||||
|  | ||||
| // Returns the copied threadpool impl of third-party/pthreadpool | ||||
| pthreadpool_t pthreadpool_create_xnnpack(size_t threads_count); | ||||
|  | ||||
| // Copied third-party impl. | ||||
| size_t pthreadpool_get_threads_count_xnnpack(pthreadpool_t threadpool); | ||||
|  | ||||
| // Copied third-party impl. | ||||
| void pthreadpool_destroy_xnnpack(pthreadpool_t threadpool); | ||||
|  | ||||
| /** | ||||
|  * Processes items in parallel using threads from a thread pool. | ||||
|  * | ||||
|  * When the call returns, all items have been processed and the thread pool is | ||||
|  * ready for a new task. | ||||
|  * | ||||
|  * @note If multiple threads call this function with the same thread pool, the | ||||
|  *    calls are serialized. | ||||
|  * | ||||
|  * @param[in]  threadpool  The thread pool to use for parallelisation. | ||||
|  * @param[in]  function    The function to call for each item. | ||||
|  * @param[in]  argument    The first argument passed to the @a function. | ||||
|  * @param[in]  items       The number of items to process. The @a function | ||||
|  *    will be called once for each item. | ||||
|  */ | ||||
| void pthreadpool_parallelize_1d( | ||||
|     pthreadpool_t threadpool, | ||||
|     pthreadpool_task_1d_t function, | ||||
|     void* argument, | ||||
|     size_t range, | ||||
|     uint32_t flags); | ||||
|  | ||||
| void pthreadpool_parallelize_1d_tile_1d( | ||||
|     pthreadpool_t threadpool, | ||||
|     pthreadpool_task_1d_tile_1d_t function, | ||||
|     void* argument, | ||||
|     size_t range, | ||||
|     size_t tile, | ||||
|     uint32_t flags); | ||||
|  | ||||
| void pthreadpool_parallelize_2d( | ||||
|     pthreadpool_t threadpool, | ||||
|     pthreadpool_task_2d_t function, | ||||
|     void* argument, | ||||
|     size_t range_i, | ||||
|     size_t range_j, | ||||
|     uint32_t flags); | ||||
|  | ||||
| void pthreadpool_parallelize_2d_tile_1d( | ||||
|     pthreadpool_t threadpool, | ||||
|     pthreadpool_task_2d_tile_1d_t function, | ||||
|     void* argument, | ||||
|     size_t range_i, | ||||
|     size_t range_j, | ||||
|     size_t tile_j, | ||||
|     uint32_t flags); | ||||
|  | ||||
| void pthreadpool_parallelize_2d_tile_2d( | ||||
|     pthreadpool_t threadpool, | ||||
|     pthreadpool_task_2d_tile_2d_t function, | ||||
|     void* argument, | ||||
|     size_t range_i, | ||||
|     size_t range_j, | ||||
|     size_t tile_i, | ||||
|     size_t tile_j, | ||||
|     uint32_t flags); | ||||
|  | ||||
| void pthreadpool_parallelize_3d_tile_2d( | ||||
|     pthreadpool_t threadpool, | ||||
|     pthreadpool_task_3d_tile_2d_t function, | ||||
|     void* argument, | ||||
|     size_t range_i, | ||||
|     size_t range_j, | ||||
|     size_t range_k, | ||||
|     size_t tile_j, | ||||
|     size_t tile_k, | ||||
|     uint32_t flags); | ||||
|  | ||||
| void pthreadpool_parallelize_4d_tile_2d( | ||||
|     pthreadpool_t threadpool, | ||||
|     pthreadpool_task_4d_tile_2d_t function, | ||||
|     void* argument, | ||||
|     size_t range_i, | ||||
|     size_t range_j, | ||||
|     size_t range_k, | ||||
|     size_t range_l, | ||||
|     size_t tile_k, | ||||
|     size_t tile_l, | ||||
|     uint32_t flags); | ||||
|  | ||||
| void pthreadpool_parallelize_5d_tile_2d( | ||||
|     pthreadpool_t threadpool, | ||||
|     pthreadpool_task_5d_tile_2d_t function, | ||||
|     void* argument, | ||||
|     size_t range_i, | ||||
|     size_t range_j, | ||||
|     size_t range_k, | ||||
|     size_t range_l, | ||||
|     size_t range_m, | ||||
|     size_t tile_l, | ||||
|     size_t tile_m, | ||||
|     uint32_t flags); | ||||
|  | ||||
| void pthreadpool_parallelize_6d_tile_2d( | ||||
|     pthreadpool_t threadpool, | ||||
|     pthreadpool_task_6d_tile_2d_t function, | ||||
|     void* argument, | ||||
|     size_t range_i, | ||||
|     size_t range_j, | ||||
|     size_t range_k, | ||||
|     size_t range_l, | ||||
|     size_t range_m, | ||||
|     size_t range_n, | ||||
|     size_t tile_m, | ||||
|     size_t tile_n, | ||||
|     uint32_t flags); | ||||
| #endif /* USE_INTERNAL_PTHREADPOOL_IMPL */ | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } /* extern "C" */ | ||||
|  | ||||
| @ -6,9 +6,9 @@ | ||||
| // External API | ||||
| // | ||||
|  | ||||
| void pthreadpool_compute_1d( | ||||
|     pthreadpool_t threadpool, | ||||
|     pthreadpool_function_1d_t function, | ||||
| void legacy_pthreadpool_compute_1d( | ||||
|     legacy_pthreadpool_t threadpool, | ||||
|     legacy_pthreadpool_function_1d_t function, | ||||
|     void* argument, | ||||
|     size_t range) { | ||||
|   if (threadpool == nullptr) { | ||||
| @ -27,30 +27,31 @@ void pthreadpool_compute_1d( | ||||
|           range); | ||||
| } | ||||
|  | ||||
| size_t pthreadpool_get_threads_count(pthreadpool_t threadpool) { | ||||
|   // The current fix only useful when XNNPACK calls pthreadpool_get_threads_count with nullptr. | ||||
| void legacy_pthreadpool_parallelize_1d( | ||||
|     const legacy_pthreadpool_t threadpool, | ||||
|     const legacy_pthreadpool_function_1d_t function, | ||||
|     void* const argument, | ||||
|     const size_t range, | ||||
|     uint32_t) { | ||||
|   legacy_pthreadpool_compute_1d(threadpool, function, argument, range); | ||||
| } | ||||
|  | ||||
| size_t legacy_pthreadpool_get_threads_count(legacy_pthreadpool_t threadpool) { | ||||
|   // The current fix only useful when XNNPACK calls legacy_pthreadpool_get_threads_count with nullptr. | ||||
|   if (threadpool == nullptr) { | ||||
|     return 1; | ||||
|   } | ||||
|   return reinterpret_cast<caffe2::ThreadPool*>(threadpool)->getNumThreads(); | ||||
|   // TODO: Future fix: If we keep maintaining two different threadpools. | ||||
|   // Old C2 and new one for XNNPACK, then the we have two different pthreadpool pointer | ||||
|   // types. One is caffe2::Thredpool*, the other is pthreadpool* (pthreadpool_new_if_impl.c) | ||||
|   // XNNPACK calls pthreadpool_get_threads_count during op setup using pthreadpool*, and | ||||
|   // uses _parallelize_ interface for for actual work. | ||||
|   // While NNPACK uses caffe2::Threadpool*. | ||||
|   // Thus if pthreadpool_get_threads_count is getting called from XNNPACK we cannot | ||||
|   // reinterpret_cast it to ThreadPool. It will seg fault or worse will have unedfined behavior. | ||||
| } | ||||
|  | ||||
| pthreadpool_t pthreadpool_create(size_t threads_count) { | ||||
| legacy_pthreadpool_t legacy_pthreadpool_create(size_t threads_count) { | ||||
|   std::mutex thread_pool_creation_mutex_; | ||||
|   std::lock_guard<std::mutex> guard(thread_pool_creation_mutex_); | ||||
|  | ||||
|   return reinterpret_cast<pthreadpool_t>(new caffe2::ThreadPool(threads_count)); | ||||
|   return reinterpret_cast<legacy_pthreadpool_t>(new caffe2::ThreadPool(threads_count)); | ||||
| } | ||||
|  | ||||
| void pthreadpool_destroy(pthreadpool_t pthreadpool) { | ||||
| void legacy_pthreadpool_destroy(legacy_pthreadpool_t pthreadpool) { | ||||
|   if (pthreadpool) { | ||||
|     caffe2::ThreadPool* threadpool = | ||||
|         reinterpret_cast<caffe2::ThreadPool*>(pthreadpool); | ||||
|  | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -1,62 +0,0 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include <stdint.h> | ||||
|  | ||||
| #if defined(__SSE__) || defined(__x86_64__) | ||||
| #include <xmmintrin.h> | ||||
| #endif | ||||
|  | ||||
| struct fpu_state { | ||||
| #if defined(__SSE__) || defined(__x86_64__) | ||||
|   uint32_t mxcsr; | ||||
| #elif defined(__arm__) && defined(__ARM_FP) && (__ARM_FP != 0) | ||||
|   uint32_t fpscr; | ||||
| #elif defined(__aarch64__) | ||||
|   uint64_t fpcr; | ||||
| #else | ||||
|   char unused; | ||||
| #endif | ||||
| }; | ||||
|  | ||||
| static inline struct fpu_state get_fpu_state() { | ||||
|   struct fpu_state state = { 0 }; | ||||
| #if defined(__SSE__) || defined(__x86_64__) | ||||
|   state.mxcsr = (uint32_t) _mm_getcsr(); | ||||
| #elif defined(__arm__) && defined(__ARM_FP) && (__ARM_FP != 0) | ||||
|   __asm__ __volatile__("VMRS %[fpscr], fpscr" : [fpscr] "=r" (state.fpscr)); | ||||
| #elif defined(__aarch64__) | ||||
|   __asm__ __volatile__("MRS %[fpcr], fpcr" : [fpcr] "=r" (state.fpcr)); | ||||
| #endif | ||||
|   return state; | ||||
| } | ||||
|  | ||||
| static inline void set_fpu_state(const struct fpu_state state) { | ||||
| #if defined(__SSE__) || defined(__x86_64__) | ||||
|   _mm_setcsr((unsigned int) state.mxcsr); | ||||
| #elif defined(__arm__) && defined(__ARM_FP) && (__ARM_FP != 0) | ||||
|   __asm__ __volatile__("VMSR fpscr, %[fpscr]" : : [fpscr] "r" (state.fpscr)); | ||||
| #elif defined(__aarch64__) | ||||
|   __asm__ __volatile__("MSR fpcr, %[fpcr]" : : [fpcr] "r" (state.fpcr)); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| static inline void disable_fpu_denormals() { | ||||
| #if defined(__SSE__) || defined(__x86_64__) | ||||
|   _mm_setcsr(_mm_getcsr() | 0x8040); | ||||
| #elif defined(__arm__) && defined(__ARM_FP) && (__ARM_FP != 0) | ||||
|   uint32_t fpscr; | ||||
|   __asm__ __volatile__( | ||||
|       "VMRS %[fpscr], fpscr\n" | ||||
|       "ORR %[fpscr], #0x1000000\n" | ||||
|       "VMSR fpscr, %[fpscr]\n" | ||||
|     : [fpscr] "=r" (fpscr)); | ||||
| #elif defined(__aarch64__) | ||||
|   uint64_t fpcr; | ||||
|   __asm__ __volatile__( | ||||
|       "MRS %[fpcr], fpcr\n" | ||||
|       "ORR %w[fpcr], %w[fpcr], 0x1000000\n" | ||||
|       "ORR %w[fpcr], %w[fpcr], 0x80000\n" | ||||
|       "MSR fpcr, %[fpcr]\n" | ||||
|     : [fpcr] "=r" (fpcr)); | ||||
| #endif | ||||
| } | ||||
| @ -239,10 +239,10 @@ if(USE_NNPACK OR USE_QNNPACK OR USE_PYTORCH_QNNPACK OR USE_XNNPACK) | ||||
|   endif() | ||||
|  | ||||
|   if(DISABLE_NNPACK_AND_FAMILY) | ||||
|     set(USE_NNPACK OFF) | ||||
|     set(USE_QNNPACK OFF) | ||||
|     set(USE_PYTORCH_QNNPACK OFF) | ||||
|     set(USE_XNNPACK OFF) | ||||
|     caffe2_update_option(USE_NNPACK OFF) | ||||
|     caffe2_update_option(USE_QNNPACK OFF) | ||||
|     caffe2_update_option(USE_PYTORCH_QNNPACK OFF) | ||||
|     caffe2_update_option(USE_XNNPACK OFF) | ||||
|   else() | ||||
|     set(CAFFE2_THIRD_PARTY_ROOT "${PROJECT_SOURCE_DIR}/third_party") | ||||
|  | ||||
| @ -261,11 +261,9 @@ if(USE_NNPACK OR USE_QNNPACK OR USE_PYTORCH_QNNPACK OR USE_XNNPACK) | ||||
|     if(NOT DEFINED PTHREADPOOL_SOURCE_DIR) | ||||
|       set(PTHREADPOOL_SOURCE_DIR "${CAFFE2_THIRD_PARTY_ROOT}/pthreadpool" CACHE STRING "pthreadpool source directory") | ||||
|     endif() | ||||
|  | ||||
|     set(CPUINFO_LIBRARY_TYPE "static" CACHE STRING "") | ||||
|     set(CPUINFO_LOG_LEVEL "error" CACHE STRING "") | ||||
|     set(PTHREADPOOL_LIBRARY_TYPE "static" CACHE STRING "") | ||||
|   endif() | ||||
| else() | ||||
|   set(DISABLE_NNPACK_AND_FAMILY ON) | ||||
| endif() | ||||
|  | ||||
| set(CONFU_DEPENDENCIES_SOURCE_DIR ${PROJECT_BINARY_DIR}/confu-srcs | ||||
| @ -281,45 +279,48 @@ if(INTERN_BUILD_MOBILE AND INTERN_USE_EIGEN_BLAS) | ||||
| endif() | ||||
|  | ||||
| # ---[ pthreadpool | ||||
| # QNNPACK and NNPACK both depend on pthreadpool, but when building with libtorch | ||||
| # they should use the pthreadpool implementation under caffe2/utils/threadpool | ||||
| # instead of the default implementation. To avoid confusion, add pthreadpool | ||||
| # subdirectory explicitly with EXCLUDE_FROM_ALL property prior to QNNPACK/NNPACK | ||||
| # does so, which will prevent it from installing the default pthreadpool library. | ||||
| if(INTERN_BUILD_MOBILE AND NOT BUILD_CAFFE2_MOBILE AND (USE_QNNPACK OR USE_NNPACK OR USE_XNNPACK)) | ||||
|   if(NOT DEFINED PTHREADPOOL_SOURCE_DIR) | ||||
|     set(CAFFE2_THIRD_PARTY_ROOT "${PROJECT_SOURCE_DIR}/third_party") | ||||
|     set(PTHREADPOOL_SOURCE_DIR "${CAFFE2_THIRD_PARTY_ROOT}/pthreadpool" CACHE STRING "pthreadpool source directory") | ||||
|   endif() | ||||
| # Only add a dependency on pthreadpool if we are on a mobile build | ||||
| # or are building any of the libraries in the {Q/X}NNPACK family. | ||||
| if(INTERN_BUILD_MOBILE OR NOT DISABLE_NNPACK_AND_FAMILY) | ||||
|   set(USE_PTHREADPOOL ON CACHE BOOL "" FORCE) | ||||
|   set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DUSE_PTHREADPOOL") | ||||
|  | ||||
|   # Always use third_party/pthreadpool. | ||||
|   set(USE_INTERNAL_PTHREADPOOL_IMPL OFF CACHE BOOL "" FORCE) | ||||
|  | ||||
|   if(NOT TARGET pthreadpool) | ||||
|     set(PTHREADPOOL_BUILD_TESTS OFF CACHE BOOL "") | ||||
|     set(PTHREADPOOL_BUILD_BENCHMARKS OFF CACHE BOOL "") | ||||
|     add_subdirectory( | ||||
|       "${PTHREADPOOL_SOURCE_DIR}" | ||||
|       "${CONFU_DEPENDENCIES_BINARY_DIR}/pthreadpool" | ||||
|       EXCLUDE_FROM_ALL) | ||||
|   endif() | ||||
| endif() | ||||
|     if(USE_SYSTEM_PTHREADPOOL) | ||||
|       add_library(pthreadpool SHARED IMPORTED) | ||||
|       find_library(PTHREADPOOL_LIBRARY pthreadpool) | ||||
|       set_property(TARGET pthreadpool PROPERTY IMPORTED_LOCATION "${PTHREADPOOL_LIBRARY}") | ||||
|       if(NOT PTHREADPOOL_LIBRARY) | ||||
|         message(FATAL_ERROR "Cannot find pthreadpool") | ||||
|       endif() | ||||
|       message("-- Found pthreadpool: ${PTHREADPOOL_LIBRARY}") | ||||
|     elseif(NOT USE_INTERNAL_PTHREADPOOL_IMPL) | ||||
|       if(NOT DEFINED PTHREADPOOL_SOURCE_DIR) | ||||
|         set(CAFFE2_THIRD_PARTY_ROOT "${PROJECT_SOURCE_DIR}/third_party") | ||||
|         set(PTHREADPOOL_SOURCE_DIR "${CAFFE2_THIRD_PARTY_ROOT}/pthreadpool" CACHE STRING "pthreadpool source directory") | ||||
|       endif() | ||||
|  | ||||
| # XNNPACK has not option of like QNNPACK_CUSTOM_THREADPOOL | ||||
| # that allows us to hijack pthreadpool interface. | ||||
| # Thus not doing this ends up building pthreadpool as well as | ||||
| # the internal implemenation of pthreadpool which results in symbol conflicts. | ||||
| if(USE_XNNPACK AND NOT USE_SYSTEM_XNNPACK) | ||||
|   if(NOT DEFINED PTHREADPOOL_SOURCE_DIR) | ||||
|     set(CAFFE2_THIRD_PARTY_ROOT "${PROJECT_SOURCE_DIR}/third_party") | ||||
|     set(PTHREADPOOL_SOURCE_DIR "${CAFFE2_THIRD_PARTY_ROOT}/pthreadpool" CACHE STRING "pthreadpool source directory") | ||||
|   endif() | ||||
|       set(PTHREADPOOL_BUILD_TESTS OFF CACHE BOOL "") | ||||
|       set(PTHREADPOOL_BUILD_BENCHMARKS OFF CACHE BOOL "") | ||||
|       set(PTHREADPOOL_LIBRARY_TYPE "static" CACHE STRING "") | ||||
|       set(PTHREADPOOL_ALLOW_DEPRECATED_API ON CACHE BOOL "") | ||||
|       add_subdirectory( | ||||
|         "${PTHREADPOOL_SOURCE_DIR}" | ||||
|         "${CONFU_DEPENDENCIES_BINARY_DIR}/pthreadpool") | ||||
|       set_property(TARGET pthreadpool PROPERTY POSITION_INDEPENDENT_CODE ON) | ||||
|     endif() | ||||
|  | ||||
|   if(NOT TARGET pthreadpool) | ||||
|     set(PTHREADPOOL_BUILD_TESTS OFF CACHE BOOL "") | ||||
|     set(PTHREADPOOL_BUILD_BENCHMARKS OFF CACHE BOOL "") | ||||
|     add_subdirectory( | ||||
|       "${PTHREADPOOL_SOURCE_DIR}" | ||||
|       "${CONFU_DEPENDENCIES_BINARY_DIR}/pthreadpool" | ||||
|       EXCLUDE_FROM_ALL) | ||||
|     if(USE_INTERNAL_PTHREADPOOL_IMPL) | ||||
|       set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DUSE_INTERNAL_PTHREADPOOL_IMPL") | ||||
|     else() | ||||
|       list(APPEND Caffe2_DEPENDENCY_LIBS pthreadpool) | ||||
|     endif() | ||||
|   endif() | ||||
| else() | ||||
|   set(USE_PTHREADPOOL OFF CACHE BOOL "" FORCE) | ||||
| endif() | ||||
|  | ||||
| # ---[ Caffe2 uses cpuinfo library in the thread pool | ||||
| @ -369,9 +370,12 @@ if(USE_QNNPACK) | ||||
|   endif() | ||||
|  | ||||
|   if(NOT TARGET qnnpack) | ||||
|     if(NOT USE_SYSTEM_PTHREADPOOL AND USE_INTERNAL_PTHREADPOOL_IMPL) | ||||
|       set(QNNPACK_CUSTOM_THREADPOOL ON CACHE BOOL "") | ||||
|     endif() | ||||
|  | ||||
|     set(QNNPACK_BUILD_TESTS OFF CACHE BOOL "") | ||||
|     set(QNNPACK_BUILD_BENCHMARKS OFF CACHE BOOL "") | ||||
|     set(QNNPACK_CUSTOM_THREADPOOL ON CACHE BOOL "") | ||||
|     set(QNNPACK_LIBRARY_TYPE "static" CACHE STRING "") | ||||
|     add_subdirectory( | ||||
|       "${QNNPACK_SOURCE_DIR}" | ||||
| @ -379,8 +383,29 @@ if(USE_QNNPACK) | ||||
|     # We build static versions of QNNPACK and pthreadpool but link | ||||
|     # them into a shared library for Caffe2, so they need PIC. | ||||
|     set_property(TARGET qnnpack PROPERTY POSITION_INDEPENDENT_CODE ON) | ||||
|     set_property(TARGET pthreadpool PROPERTY POSITION_INDEPENDENT_CODE ON) | ||||
|     set_property(TARGET cpuinfo PROPERTY POSITION_INDEPENDENT_CODE ON) | ||||
|  | ||||
|     if(QNNPACK_CUSTOM_THREADPOOL) | ||||
|       target_compile_definitions( | ||||
|         qnnpack PRIVATE | ||||
|         pthreadpool_t=legacy_pthreadpool_t | ||||
|         pthreadpool_function_1d_t=legacy_pthreadpool_function_1d_t | ||||
|         pthreadpool_function_1d_tiled_t=legacy_pthreadpool_function_1d_tiled_t | ||||
|         pthreadpool_function_2d_t=legacy_pthreadpool_function_2d_t | ||||
|         pthreadpool_function_2d_tiled_t=legacy_pthreadpool_function_2d_tiled_t | ||||
|         pthreadpool_function_3d_tiled_t=legacy_pthreadpool_function_3d_tiled_t | ||||
|         pthreadpool_function_4d_tiled_t=legacy_pthreadpool_function_4d_tiled_t | ||||
|         pthreadpool_create=legacy_pthreadpool_create | ||||
|         pthreadpool_destroy=legacy_pthreadpool_destroy | ||||
|         pthreadpool_get_threads_count=legacy_pthreadpool_get_threads_count | ||||
|         pthreadpool_compute_1d=legacy_pthreadpool_compute_1d | ||||
|         pthreadpool_parallelize_1d=legacy_pthreadpool_parallelize_1d | ||||
|         pthreadpool_compute_1d_tiled=legacy_pthreadpool_compute_1d_tiled | ||||
|         pthreadpool_compute_2d=legacy_pthreadpool_compute_2d | ||||
|         pthreadpool_compute_2d_tiled=legacy_pthreadpool_compute_2d_tiled | ||||
|         pthreadpool_compute_3d_tiled=legacy_pthreadpool_compute_3d_tiled | ||||
|         pthreadpool_compute_4d_tiled=legacy_pthreadpool_compute_4d_tiled) | ||||
|     endif() | ||||
|   endif() | ||||
|  | ||||
|   list(APPEND Caffe2_DEPENDENCY_LIBS qnnpack) | ||||
| @ -400,9 +425,12 @@ if(USE_PYTORCH_QNNPACK) | ||||
|     endif() | ||||
|  | ||||
|     if(NOT TARGET pytorch_qnnpack) | ||||
|       if(NOT USE_SYSTEM_PTHREADPOOL AND USE_INTERNAL_PTHREADPOOL_IMPL) | ||||
|         set(PYTORCH_QNNPACK_CUSTOM_THREADPOOL ON CACHE BOOL "") | ||||
|       endif() | ||||
|  | ||||
|       set(PYTORCH_QNNPACK_BUILD_TESTS OFF CACHE BOOL "") | ||||
|       set(PYTORCH_QNNPACK_BUILD_BENCHMARKS OFF CACHE BOOL "") | ||||
|       set(PYTORCH_QNNPACK_CUSTOM_THREADPOOL ON CACHE BOOL "") | ||||
|       set(PYTORCH_QNNPACK_LIBRARY_TYPE "static" CACHE STRING "") | ||||
|       add_subdirectory( | ||||
|         "${PYTORCH_QNNPACK_SOURCE_DIR}" | ||||
| @ -410,10 +438,29 @@ if(USE_PYTORCH_QNNPACK) | ||||
|       # We build static versions of QNNPACK and pthreadpool but link | ||||
|       # them into a shared library for Caffe2, so they need PIC. | ||||
|       set_property(TARGET pytorch_qnnpack PROPERTY POSITION_INDEPENDENT_CODE ON) | ||||
|       if(NOT USE_SYSTEM_PTHREADPOOL) | ||||
|         set_property(TARGET pthreadpool PROPERTY POSITION_INDEPENDENT_CODE ON) | ||||
|       endif() | ||||
|       set_property(TARGET cpuinfo PROPERTY POSITION_INDEPENDENT_CODE ON) | ||||
|  | ||||
|       if(PYTORCH_QNNPACK_CUSTOM_THREADPOOL) | ||||
|         target_compile_definitions( | ||||
|           pytorch_qnnpack PRIVATE | ||||
|           pthreadpool_t=legacy_pthreadpool_t | ||||
|           pthreadpool_function_1d_t=legacy_pthreadpool_function_1d_t | ||||
|           pthreadpool_function_1d_tiled_t=legacy_pthreadpool_function_1d_tiled_t | ||||
|           pthreadpool_function_2d_t=legacy_pthreadpool_function_2d_t | ||||
|           pthreadpool_function_2d_tiled_t=legacy_pthreadpool_function_2d_tiled_t | ||||
|           pthreadpool_function_3d_tiled_t=legacy_pthreadpool_function_3d_tiled_t | ||||
|           pthreadpool_function_4d_tiled_t=legacy_pthreadpool_function_4d_tiled_t | ||||
|           pthreadpool_create=legacy_pthreadpool_create | ||||
|           pthreadpool_destroy=legacy_pthreadpool_destroy | ||||
|           pthreadpool_get_threads_count=legacy_pthreadpool_get_threads_count | ||||
|           pthreadpool_compute_1d=legacy_pthreadpool_compute_1d | ||||
|           pthreadpool_parallelize_1d=legacy_pthreadpool_parallelize_1d | ||||
|           pthreadpool_compute_1d_tiled=legacy_pthreadpool_compute_1d_tiled | ||||
|           pthreadpool_compute_2d=legacy_pthreadpool_compute_2d | ||||
|           pthreadpool_compute_2d_tiled=legacy_pthreadpool_compute_2d_tiled | ||||
|           pthreadpool_compute_3d_tiled=legacy_pthreadpool_compute_3d_tiled | ||||
|           pthreadpool_compute_4d_tiled=legacy_pthreadpool_compute_4d_tiled) | ||||
|       endif() | ||||
|     endif() | ||||
|  | ||||
|     list(APPEND Caffe2_DEPENDENCY_LIBS pytorch_qnnpack) | ||||
| @ -447,7 +494,6 @@ if(USE_XNNPACK AND NOT USE_SYSTEM_XNNPACK) | ||||
|   endif() | ||||
|  | ||||
|   if(NOT TARGET XNNPACK) | ||||
|     set(XNNPACK_CUSTOM_THREADPOOL ON CACHE BOOL "") | ||||
|     set(XNNPACK_LIBRARY_TYPE "static" CACHE STRING "") | ||||
|     set(XNNPACK_BUILD_BENCHMARKS OFF CACHE BOOL "") | ||||
|     set(XNNPACK_BUILD_TESTS OFF CACHE BOOL "") | ||||
| @ -457,15 +503,6 @@ if(USE_XNNPACK AND NOT USE_SYSTEM_XNNPACK) | ||||
|       "${CONFU_DEPENDENCIES_BINARY_DIR}/XNNPACK") | ||||
|  | ||||
|     set_property(TARGET XNNPACK PROPERTY POSITION_INDEPENDENT_CODE ON) | ||||
|     # Context: pthreadpool_get_threads_count implementation that is built in pytorch, uses | ||||
|     # implementation defined in caffe2/utils/threadpool/pthreadpool_impl.cc. This implementation | ||||
|     # assumes the the pthreadpool* passed is of type caffe2::ThradPool and thus does reinterpret cast. | ||||
|     # This is not valid when we create pthreadpool via caffe2::xnnpack_threadpool, which is of type | ||||
|     # compatible with new pthreadpool interface and is used in PT's XNNPACK integration. | ||||
|     # Thus all the calls for pthreadpool_get_threads_count originating from XNNPACK must be routed | ||||
|     # appropriately to pthreadpool_get_threads_count_xnnpack, which does not do the aforementioned | ||||
|     # casting to caffe2::ThradPool. Once the threadpools are unified, we will not need this. | ||||
|     target_compile_definitions(XNNPACK PRIVATE -Dpthreadpool_get_threads_count=pthreadpool_get_threads_count_xnnpack) | ||||
|   endif() | ||||
|  | ||||
|   include_directories(SYSTEM ${XNNPACK_INCLUDE_DIR}) | ||||
|  | ||||
							
								
								
									
										27
									
								
								cmake/External/nnpack.cmake
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										27
									
								
								cmake/External/nnpack.cmake
									
									
									
									
										vendored
									
									
								
							| @ -59,9 +59,12 @@ if(ANDROID OR IOS OR ${CMAKE_SYSTEM_NAME} STREQUAL "Linux" OR ${CMAKE_SYSTEM_NAM | ||||
|   set(GOOGLETEST_SOURCE_DIR "${CAFFE2_THIRD_PARTY_ROOT}/googletest" CACHE STRING "Google Test source directory") | ||||
|  | ||||
|   if(NOT TARGET nnpack) | ||||
|     if(NOT USE_SYSTEM_PTHREADPOOL AND USE_INTERNAL_PTHREADPOOL_IMPL) | ||||
|       set(NNPACK_CUSTOM_THREADPOOL ON CACHE BOOL "") | ||||
|     endif() | ||||
|  | ||||
|     set(NNPACK_BUILD_TESTS OFF CACHE BOOL "") | ||||
|     set(NNPACK_BUILD_BENCHMARKS OFF CACHE BOOL "") | ||||
|     set(NNPACK_CUSTOM_THREADPOOL ON CACHE BOOL "") | ||||
|     set(NNPACK_LIBRARY_TYPE "static" CACHE STRING "") | ||||
|     set(PTHREADPOOL_LIBRARY_TYPE "static" CACHE STRING "") | ||||
|     set(CPUINFO_LIBRARY_TYPE "static" CACHE STRING "") | ||||
| @ -73,6 +76,28 @@ if(ANDROID OR IOS OR ${CMAKE_SYSTEM_NAME} STREQUAL "Linux" OR ${CMAKE_SYSTEM_NAM | ||||
|     set_property(TARGET nnpack PROPERTY POSITION_INDEPENDENT_CODE ON) | ||||
|     set_property(TARGET pthreadpool PROPERTY POSITION_INDEPENDENT_CODE ON) | ||||
|     set_property(TARGET cpuinfo PROPERTY POSITION_INDEPENDENT_CODE ON) | ||||
|  | ||||
|     if(NNPACK_CUSTOM_THREADPOOL) | ||||
|       target_compile_definitions( | ||||
|         nnpack PRIVATE | ||||
|         pthreadpool_t=legacy_pthreadpool_t | ||||
|         pthreadpool_function_1d_t=legacy_pthreadpool_function_1d_t | ||||
|         pthreadpool_function_1d_tiled_t=legacy_pthreadpool_function_1d_tiled_t | ||||
|         pthreadpool_function_2d_t=legacy_pthreadpool_function_2d_t | ||||
|         pthreadpool_function_2d_tiled_t=legacy_pthreadpool_function_2d_tiled_t | ||||
|         pthreadpool_function_3d_tiled_t=legacy_pthreadpool_function_3d_tiled_t | ||||
|         pthreadpool_function_4d_tiled_t=legacy_pthreadpool_function_4d_tiled_t | ||||
|         pthreadpool_create=legacy_pthreadpool_create | ||||
|         pthreadpool_destroy=legacy_pthreadpool_destroy | ||||
|         pthreadpool_get_threads_count=legacy_pthreadpool_get_threads_count | ||||
|         pthreadpool_compute_1d=legacy_pthreadpool_compute_1d | ||||
|         pthreadpool_parallelize_1d=legacy_pthreadpool_parallelize_1d | ||||
|         pthreadpool_compute_1d_tiled=legacy_pthreadpool_compute_1d_tiled | ||||
|         pthreadpool_compute_2d=legacy_pthreadpool_compute_2d | ||||
|         pthreadpool_compute_2d_tiled=legacy_pthreadpool_compute_2d_tiled | ||||
|         pthreadpool_compute_3d_tiled=legacy_pthreadpool_compute_3d_tiled | ||||
|         pthreadpool_compute_4d_tiled=legacy_pthreadpool_compute_4d_tiled) | ||||
|     endif() | ||||
|   endif() | ||||
|  | ||||
|   set(NNPACK_FOUND TRUE) | ||||
|  | ||||
| @ -69,6 +69,11 @@ if(NOT @BUILD_SHARED_LIBS@) | ||||
|     list(APPEND TORCH_LIBRARIES ${XNNPACK_LIBRARY}) | ||||
|   endif() | ||||
|  | ||||
|   if(NOT @USE_INTERNAL_PTHREADPOOL_IMPL@) | ||||
|     find_library(PTHREADPOOL_LIBRARY pthreadpool PATHS "${TORCH_INSTALL_PREFIX}/lib") | ||||
|     list(APPEND TORCH_LIBRARIES ${PTHREADPOOL_LIBRARY}) | ||||
|   endif() | ||||
|  | ||||
|   if(@INTERN_USE_EIGEN_BLAS@) | ||||
|     find_library(EIGEN_BLAS_LIBRARY eigen_blas PATHS "${TORCH_INSTALL_PREFIX}/lib") | ||||
|     list(APPEND TORCH_LIBRARIES ${EIGEN_BLAS_LIBRARY}) | ||||
|  | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user
	