Skip to content

Commit

Permalink
Revert D16048264: Add static dispatch mode to reduce mobile code size
Browse files Browse the repository at this point in the history
Differential Revision:
D16048264

Original commit changeset: ad1e50951273

fbshipit-source-id: 69d302929e183e2da26b64dcc24c69c3b7de186b
  • Loading branch information
luciang authored and facebook-github-bot committed Aug 20, 2019
1 parent 8ca6220 commit bd6cf50
Show file tree
Hide file tree
Showing 17 changed files with 39 additions and 3,228 deletions.
6 changes: 1 addition & 5 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,6 @@ pytorch_linux_build_defaults: &pytorch_linux_build_defaults
NAMED_FLAG="export BUILD_NAMEDTENSOR=1"
fi
# dispatch aten ops statically for mobile
if [[ ${BUILD_ENVIRONMENT} == *"android"* ]]; then
NAMED_FLAG="export USE_STATIC_DISPATCH=1"
fi
export COMMAND='((echo "export BUILD_ENVIRONMENT=${BUILD_ENVIRONMENT}" && echo '"$NAMED_FLAG"' && echo "source ./workspace/env" && echo "sudo chown -R jenkins workspace && cd workspace && .jenkins/pytorch/build.sh") | docker exec -u jenkins -i "$id" bash) 2>&1'
echo ${COMMAND} > ./command.sh && unbuffer bash ./command.sh | ts
Expand Down Expand Up @@ -300,6 +295,7 @@ caffe2_linux_test_defaults: &caffe2_linux_test_defaults
export COMMAND='((echo "source ./workspace/env" && echo "sudo chown -R jenkins workspace && cd workspace && ./ci_test_script.sh") | docker exec -u jenkins -i "$id" bash) 2>&1'
echo ${COMMAND} > ./command.sh && unbuffer bash ./command.sh | ts
##############################################################################
# Macos build defaults
##############################################################################
Expand Down
6 changes: 1 addition & 5 deletions .circleci/verbatim-sources/linux-build-defaults.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,6 @@ pytorch_linux_build_defaults: &pytorch_linux_build_defaults
NAMED_FLAG="export BUILD_NAMEDTENSOR=1"
fi
# dispatch aten ops statically for mobile
if [[ ${BUILD_ENVIRONMENT} == *"android"* ]]; then
NAMED_FLAG="export USE_STATIC_DISPATCH=1"
fi
export COMMAND='((echo "export BUILD_ENVIRONMENT=${BUILD_ENVIRONMENT}" && echo '"$NAMED_FLAG"' && echo "source ./workspace/env" && echo "sudo chown -R jenkins workspace && cd workspace && .jenkins/pytorch/build.sh") | docker exec -u jenkins -i "$id" bash) 2>&1'
echo ${COMMAND} > ./command.sh && unbuffer bash ./command.sh | ts
Expand Down Expand Up @@ -236,3 +231,4 @@ caffe2_linux_test_defaults: &caffe2_linux_test_defaults
export COMMAND='((echo "source ./workspace/env" && echo "sudo chown -R jenkins workspace && cd workspace && ./ci_test_script.sh") | docker exec -u jenkins -i "$id" bash) 2>&1'
echo ${COMMAND} > ./command.sh && unbuffer bash ./command.sh | ts
6 changes: 0 additions & 6 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ option(BUILD_CAFFE2_OPS "Build Caffe2 operators" ON)
option(BUILD_SHARED_LIBS "Build libcaffe2.so" ON)
option(BUILD_CAFFE2_MOBILE "Build libcaffe2 for mobile (deprecating)" ON)
option(BUILD_NAMEDTENSOR "Experimental: compile with namedtensor support" OFF)
option(USE_STATIC_DISPATCH "Use static dispatch for ATen operators" OFF)
cmake_dependent_option(
CAFFE2_LINK_LOCAL_PROTOBUF "If set, build protobuf inside libcaffe2.so." ON
"BUILD_SHARED_LIBS AND BUILD_CUSTOM_PROTOBUF" OFF)
Expand Down Expand Up @@ -318,10 +317,6 @@ if(USE_QNNPACK)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DUSE_QNNPACK")
endif()

if(USE_STATIC_DISPATCH)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DUSE_STATIC_DISPATCH")
endif()

# ---[ Whitelist file if whitelist is specified
include(cmake/Whitelist.cmake)

Expand Down Expand Up @@ -467,7 +462,6 @@ include_directories(BEFORE ${PROJECT_SOURCE_DIR})
include_directories(BEFORE ${PROJECT_BINARY_DIR})

include_directories(BEFORE ${PROJECT_SOURCE_DIR}/aten/src/)
include_directories(BEFORE ${PROJECT_BINARY_DIR}/aten/src/)

# ---[ Main build
add_subdirectory(c10)
Expand Down
1 change: 0 additions & 1 deletion aten/src/ATen/ScalarOps.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

#include <c10/core/Scalar.h>
#include <ATen/Tensor.h>
#include <ATen/Functions.h>

// This is in the c10 namespace because we use ADL to find the functions in it.
namespace c10 {
Expand Down
18 changes: 0 additions & 18 deletions aten/src/ATen/core/Tensor.h
Original file line number Diff line number Diff line change
Expand Up @@ -837,24 +837,6 @@ template <typename T, typename... Args>
Tensor make_tensor(Args&&... args) {
return Tensor(c10::make_intrusive<T>(std::forward<Args>(args)...));
}

inline Backend infer_backend(const Tensor & t) {
TORCH_CHECK(t.defined(), "undefined Tensor");
return tensorTypeIdToBackend(t.type_id());
}
inline Backend infer_backend(const TensorList & tl) {
TORCH_CHECK(tl.size() > 0, "expected a non-empty list of Tensors");
return tensorTypeIdToBackend(tl[0].type_id());
}

inline bool infer_is_variable(const Tensor & t) {
TORCH_CHECK(t.defined(), "undefined Tensor");
return t.is_variable();
}
inline bool infer_is_variable(const TensorList & tl) {
TORCH_CHECK(tl.size() > 0, "expected a non-empty list of Tensors");
return tl[0].is_variable();
}
} // namespace detail

} // namespace at
Expand Down
3,023 changes: 0 additions & 3,023 deletions aten/src/ATen/core/TensorMethods.h

Large diffs are not rendered by default.

76 changes: 4 additions & 72 deletions aten/src/ATen/function_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,12 +131,8 @@ def TypedDict(name, attrs, total=True): # type: ignore
# add non-virtual declaration to Tensor.cpp
TENSOR_METHOD_DEFINITION = CodeTemplate("""\
inline ${return_type} Tensor::${api_name}(${method_formals}) const {
#ifdef USE_STATIC_DISPATCH
${mobile_method_body}
#else
static auto table = globalATenDispatch().getOpTable("${schema_string}");
return table->getOp<${return_type} (${formals_types})>(tensorTypeIdToBackend(type_id()), is_variable())(${method_actuals});
#endif
}
""")
# add a method declaration in Functions.h
Expand All @@ -150,33 +146,10 @@ def TypedDict(name, attrs, total=True): # type: ignore
# add method definition in Functions.h
FUNCTION_DEFINITION = CodeTemplate("""\
static inline ${return_type} ${api_name}(${formals}) {
#ifdef USE_STATIC_DISPATCH
${mobile_function_body}
#else
static auto table = globalATenDispatch().getOpTable("${schema_string}");
return table->getOp<${return_type} (${formals_types})>(${inferred_backend}, ${inferred_is_variable})(${native_actuals});
#endif
}
""")

# for mobile builds, we rely on the linker to strip unused ops.
# this requires us to dispatch statically in Functions.h and TensorMethods.h
MOBILE_FUNCTION_DEFAULT_BODY = CodeTemplate("""\
${return_call} TypeDefault::${native_type_method_dispatch}(${native_arguments});
""")
MOBILE_FUNCTION_SWITCH_BODY = CodeTemplate("""\
switch(${backend}) {
${mobile_function_switches}
default:
AT_ERROR("${api_name} not implemented for ", at::toString(${backend}));
}
""")
MOBILE_FUNCTION_SWITCH_STATEMENT = CodeTemplate("""\
case Backend::${backend}:
${return_call} ${backend}Type::${api_name}(${native_arguments});
break;
""")

# add a native declaration for a native function
NATIVE_DECLARATION = CodeTemplate("""\
CAFFE2_API ${return_type} ${native_type_method_dispatch}(${formals_with_defaults});
Expand All @@ -185,13 +158,9 @@ def TypedDict(name, attrs, total=True): # type: ignore
# special method definition for factory functions in Functions.h that initializes backends
FACTORY_DEFINITION = CodeTemplate("""\
static inline ${return_type} ${api_name}(${formals}) {
#ifdef USE_STATIC_DISPATCH
${mobile_function_body}
#else
globalLegacyTypeDispatch().initForBackend(${inferred_backend});
static auto table = globalATenDispatch().getOpTable("${schema_string}");
return table->getOp<${return_type} (${formals_types})>(${inferred_backend}, ${inferred_is_variable})(${native_actuals});
#endif
}
""")

Expand Down Expand Up @@ -236,8 +205,6 @@ def TypedDict(name, attrs, total=True): # type: ignore
('BFloat16', 'BFloat16', 'BFloat16AccrealNotDefined', True),
]

mobile_backends = ['CPU', 'QuantizedCPU', 'SparseCPU']


class NYIError(Exception):
"""Indicates we don't support this declaration yet"""
Expand Down Expand Up @@ -1092,26 +1059,9 @@ def has_named_tensor_formals(formals):

def gen_tensor_method(option):
# type: (Any) -> FunctionCode
if isinstance(type_method_dispatch, dict):
mobile_function_switches = []
for backend in mobile_backends:
if backend in type_method_dispatch:
mobile_function_switches.append(MOBILE_FUNCTION_SWITCH_STATEMENT.substitute(
option,
backend=backend,
backend_function=type_method_dispatch[backend],
native_arguments=option['method_actuals']))
mobile_method_body = MOBILE_FUNCTION_SWITCH_BODY.substitute(
option,
backend='tensorTypeIdToBackend(type_id())',
mobile_function_switches=mobile_function_switches)
else:
mobile_method_body = MOBILE_FUNCTION_DEFAULT_BODY.substitute(
option, native_arguments=option['method_actuals'])

return FunctionCode(
declaration=TENSOR_METHOD_DECLARATION.substitute(option, mobile_method_body=mobile_method_body),
definition=TENSOR_METHOD_DEFINITION.substitute(option, mobile_method_body=mobile_method_body))
declaration=TENSOR_METHOD_DECLARATION.substitute(option),
definition=TENSOR_METHOD_DEFINITION.substitute(option))

def gen_namespace_function(option, dispatch_tensor, dispatch_options):
# type: (Any, Optional[str], Any) -> FunctionCode
Expand All @@ -1127,28 +1077,10 @@ def gen_namespace_function(option, dispatch_tensor, dispatch_options):
option['inferred_is_variable'] = 'false'
declaration = DEPRECATED_FUNCTION_DECLARATION if option['deprecated'] else FUNCTION_DECLARATION
fn_declaration = declaration.substitute(option)

if isinstance(type_method_dispatch, dict):
mobile_function_switches = []
for backend in mobile_backends:
if backend in type_method_dispatch:
mobile_function_switches.append(MOBILE_FUNCTION_SWITCH_STATEMENT.substitute(
option,
backend=backend,
backend_function=type_method_dispatch[backend],
native_arguments=option['native_actuals']))
mobile_function_body = MOBILE_FUNCTION_SWITCH_BODY.substitute(
option,
backend=option['inferred_backend'],
mobile_function_switches=mobile_function_switches)
else:
mobile_function_body = MOBILE_FUNCTION_DEFAULT_BODY.substitute(
option, native_arguments=option['native_actuals'])

if is_factory_method:
fn_definition = FACTORY_DEFINITION.substitute(option, mobile_function_body=mobile_function_body)
fn_definition = FACTORY_DEFINITION.substitute(option)
else:
fn_definition = FUNCTION_DEFINITION.substitute(option, mobile_function_body=mobile_function_body)
fn_definition = FUNCTION_DEFINITION.substitute(option)
return FunctionCode(definition=fn_definition, declaration=fn_declaration)

# Emit #ifdef BUILD_NAMEDTENSOR macros for any code generated here
Expand Down
8 changes: 2 additions & 6 deletions aten/src/ATen/native/native_functions.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2758,9 +2758,7 @@
# legacy method
- func: _dimI(Tensor self) -> int
variants: method
dispatch:
SparseCPU: sparse_dim_sparse
SparseCUDA: sparse_dim_sparse
dispatch: sparse_dim_sparse
requires_tensor: True
device_guard: False

Expand All @@ -2776,9 +2774,7 @@
# legacy method
- func: _dimV(Tensor self) -> int
variants: method
dispatch:
SparseCPU: dense_dim_sparse
SparseCUDA: dense_dim_sparse
dispatch: dense_dim_sparse
requires_tensor: True
device_guard: False

Expand Down
23 changes: 23 additions & 0 deletions aten/src/ATen/templates/Functions.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,29 @@ inline Tensor from_blob(
return from_blob(data, sizes, detail::defaultStrides(sizes), [](void*) {}, options);
}

namespace detail {

static inline Backend infer_backend(const Tensor & t) {
TORCH_CHECK(t.defined(), "undefined Tensor");
return tensorTypeIdToBackend(t.type_id());
}
static inline Backend infer_backend(const TensorList & tl) {
TORCH_CHECK(tl.size() > 0, "expected a non-empty list of Tensors");
return tensorTypeIdToBackend(tl[0].type_id());
}

static inline bool infer_is_variable(const Tensor & t) {
TORCH_CHECK(t.defined(), "undefined Tensor");
return t.is_variable();
}
static inline bool infer_is_variable(const TensorList & tl) {
TORCH_CHECK(tl.size() > 0, "expected a non-empty list of Tensors");
return tl[0].is_variable();
}


} // namespace detail

// function definitions are all static inline because
// they are one-line statically dispatched functions that
// invoke the actual dynamic dispatch on the correct argument
Expand Down
13 changes: 1 addition & 12 deletions aten/src/ATen/templates/LegacyTHFunctions.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,7 @@

// ${generated_comment}

#include <ATen/Context.h>
#include <c10/core/ScalarType.h>
#include <c10/core/TensorOptions.h>

namespace c10 {
class Scalar;
}
namespace at {
struct Generator;
class Tensor;
struct Type;
} // namespace at
#include <ATen/ATen.h>

namespace at {
namespace native {
Expand Down
18 changes: 0 additions & 18 deletions aten/src/ATen/templates/Tensor.h
Original file line number Diff line number Diff line change
Expand Up @@ -396,24 +396,6 @@ template <typename T, typename... Args>
Tensor make_tensor(Args&&... args) {
return Tensor(c10::make_intrusive<T>(std::forward<Args>(args)...));
}

inline Backend infer_backend(const Tensor & t) {
TORCH_CHECK(t.defined(), "undefined Tensor");
return tensorTypeIdToBackend(t.type_id());
}
inline Backend infer_backend(const TensorList & tl) {
TORCH_CHECK(tl.size() > 0, "expected a non-empty list of Tensors");
return tensorTypeIdToBackend(tl[0].type_id());
}

inline bool infer_is_variable(const Tensor & t) {
TORCH_CHECK(t.defined(), "undefined Tensor");
return t.is_variable();
}
inline bool infer_is_variable(const TensorList & tl) {
TORCH_CHECK(tl.size() > 0, "expected a non-empty list of Tensors");
return tl[0].is_variable();
}
} // namespace detail

} // namespace at
Expand Down
6 changes: 0 additions & 6 deletions aten/src/ATen/templates/TensorMethods.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,6 @@
#ifdef BUILD_NAMEDTENSOR
#include <ATen/NamedTensor.h>
#endif
#ifdef USE_STATIC_DISPATCH
#include <ATen/TypeDefault.h>
#include <ATen/CPUType.h>
#include <ATen/QuantizedCPUType.h>
#include <ATen/SparseCPUType.h>
#endif

namespace at {

Expand Down
28 changes: 3 additions & 25 deletions aten/src/ATen/templates/TypeDefault.h
Original file line number Diff line number Diff line change
@@ -1,34 +1,12 @@
#pragma once

// ${generated_comment}

#include <c10/core/TensorOptions.h>
#include <c10/core/Scalar.h>
#include <c10/core/QScheme.h>
#include <c10/core/MemoryFormat.h>
#include <c10/util/ArrayRef.h>
#include <c10/util/intrusive_ptr.h>
#include <torch/csrc/WindowsTorchApiMacro.h>
#include <ATen/ATen.h>

namespace c10 {
struct Storage;
}
// ${generated_comment}

namespace at {

class Tensor;
using TensorList = ArrayRef<Tensor>;

class Context;
struct Generator;

struct Quantizer;
// This is temporary typedef to enable Quantizer in aten native function API
// we'll remove them when we are actually exposing Quantizer class
// to frontend
using ConstQuantizerPtr = const c10::intrusive_ptr<Quantizer>&;

struct TORCH_API TypeDefault {
struct CAFFE2_API TypeDefault {
${type_method_declarations}
};

Expand Down
Loading

0 comments on commit bd6cf50

Please sign in to comment.