diff --git a/scripts/generate_wrappers.py b/scripts/generate_wrappers.py index 2ac41ceca..79b3798db 100644 --- a/scripts/generate_wrappers.py +++ b/scripts/generate_wrappers.py @@ -1534,18 +1534,36 @@ def _append_unique(declaration, definition): declarations.append(declaration) definitions.append(definition) - _append_unique( - f"extern template std::vector " - f"Operator<{op_type}>::active_implementation_indices(Device::Type);", - f"template std::vector " - f"Operator<{op_type}>::active_implementation_indices(Device::Type);", + active_implementation_declaration = ( + "template <>\n" + "std::vector\n" + f"Operator<{op_type}>::active_implementation_indices(Device::Type);" + ) + active_implementation_definition = ( + "template <>\n" + "std::vector\n" + f"Operator<{op_type}>::active_implementation_indices(" + "Device::Type dev_type) {\n" + f" return detail::ActiveImplementationIndices<{op_type}>(dev_type);\n" + "}" ) + _append_unique(active_implementation_declaration, active_implementation_definition) + default_implementation_declaration = ( + "template <>\n" + "std::size_t\n" + f"Operator<{op_type}>::DefaultImplementationIndex(Device::Type);" + ) + default_implementation_definition = ( + "template <>\n" + "std::size_t\n" + f"Operator<{op_type}>::DefaultImplementationIndex(" + "Device::Type dev_type) {\n" + f" return detail::DefaultImplementationIndex<{op_type}>(dev_type);\n" + "}" + ) _append_unique( - f"extern template std::size_t " - f"Operator<{op_type}>::DefaultImplementationIndex(Device::Type);", - f"template std::size_t " - f"Operator<{op_type}>::DefaultImplementationIndex(Device::Type);", + default_implementation_declaration, default_implementation_definition ) for call in operator.calls: diff --git a/src/operator.h b/src/operator.h index 18f242fa7..093becb71 100644 --- a/src/operator.h +++ b/src/operator.h @@ -157,6 +157,15 @@ struct CacheKeyBuilder { template struct ActiveImplementations; +namespace detail { + +template +std::vector ActiveImplementationIndices(Device::Type dev_type); +template +std::size_t DefaultImplementationIndex(Device::Type dev_type); + +} // namespace detail + class OperatorBase { public: virtual ~OperatorBase() = default; @@ -297,20 +306,7 @@ class Operator : public OperatorBase { static std::vector active_implementation_indices( Device::Type dev_type) { - if (!detail::ListContains(dev_type, ActiveDevices{})) { - return {}; - } - - std::vector result; - DispatchFunc>( - dev_type, - [&](auto device_tag) { - constexpr Device::Type kDev = decltype(device_tag)::value; - result = detail::ListToVector( - typename ActiveImplementations::type{}); - }, - "Operator::active_implementation_indices"); - return result; + return detail::ActiveImplementationIndices(dev_type); } template @@ -334,30 +330,8 @@ class Operator : public OperatorBase { static constexpr std::size_t implementation_index_{implementation_index}; private: - template - static constexpr std::size_t FirstActiveImplementationIndex( - List) { - return static_cast(first); - } - - static std::size_t FirstActiveImplementationIndex(List<>) { - assert(false && "operator has no active implementation for this device"); - std::abort(); - } - static std::size_t DefaultImplementationIndex(Device::Type dev_type) { - std::size_t default_index{0}; - - DispatchFunc>( - dev_type, - [&](auto device_tag) { - constexpr Device::Type kDev = decltype(device_tag)::value; - default_index = FirstActiveImplementationIndex( - typename ActiveImplementations::type{}); - }, - "Operator::DefaultImplementationIndex"); - - return default_index; + return detail::DefaultImplementationIndex(dev_type); } static Config DefaultConfig(Device::Type dev_type) { @@ -458,6 +432,54 @@ struct ActiveImplementations { Key, kDev, std::make_index_sequence>::type; }; +namespace detail { + +template +constexpr std::size_t FirstActiveImplementationIndex(List) { + return static_cast(first); +} + +inline std::size_t FirstActiveImplementationIndex(List<>) { + assert(false && "operator has no active implementation for this device"); + std::abort(); +} + +template +std::size_t DefaultImplementationIndex(Device::Type dev_type) { + std::size_t default_index{0}; + + DispatchFunc>( + dev_type, + [&](auto device_tag) { + constexpr Device::Type kDev = decltype(device_tag)::value; + default_index = FirstActiveImplementationIndex( + typename ActiveImplementations::type{}); + }, + "Operator::DefaultImplementationIndex"); + + return default_index; +} + +template +std::vector ActiveImplementationIndices(Device::Type dev_type) { + if (!ListContains(dev_type, ActiveDevices{})) { + return {}; + } + + std::vector result; + DispatchFunc>( + dev_type, + [&](auto device_tag) { + constexpr Device::Type kDev = decltype(device_tag)::value; + result = + ListToVector(typename ActiveImplementations::type{}); + }, + "Operator::active_implementation_indices"); + return result; +} + +} // namespace detail + } // namespace infini::ops #endif diff --git a/tests/test_cpp_api.py b/tests/test_cpp_api.py index 2cbd2962f..594c68408 100644 --- a/tests/test_cpp_api.py +++ b/tests/test_cpp_api.py @@ -18,6 +18,7 @@ def test_cpp_operator_call_instantiation_smoke(tmp_path): [ _compiler("CXX", "c++"), "-std=c++17", + "-O3", "-Werror", f"-I{include_dir}", str(source), diff --git a/tests/test_generate_wrappers.py b/tests/test_generate_wrappers.py index 90e3930a7..f977cec0c 100644 --- a/tests/test_generate_wrappers.py +++ b/tests/test_generate_wrappers.py @@ -97,12 +97,22 @@ def test_operator_call_instantiations_externalize_default_implementation_lookup( operator ) - signature = ( - "std::size_t " + declaration = ( + "template <>\n" + "std::size_t\n" "Operator<::infini::ops::Abs>::DefaultImplementationIndex(Device::Type);" ) - assert f"extern template {signature}" in declarations - assert f"template {signature}" in definitions + definition = ( + "template <>\n" + "std::size_t\n" + "Operator<::infini::ops::Abs>::DefaultImplementationIndex(" + "Device::Type dev_type) {\n" + " return detail::DefaultImplementationIndex<::infini::ops::Abs>(" + "dev_type);\n" + "}" + ) + assert declaration in declarations + assert definition in definitions def test_operator_call_instantiations_externalize_active_implementation_query(): @@ -113,12 +123,22 @@ def test_operator_call_instantiations_externalize_active_implementation_query(): operator ) - signature = ( - "std::vector " + declaration = ( + "template <>\n" + "std::vector\n" "Operator<::infini::ops::Add>::active_implementation_indices(Device::Type);" ) - assert f"extern template {signature}" in declarations - assert f"template {signature}" in definitions + definition = ( + "template <>\n" + "std::vector\n" + "Operator<::infini::ops::Add>::active_implementation_indices(" + "Device::Type dev_type) {\n" + " return detail::ActiveImplementationIndices<::infini::ops::Add>(" + "dev_type);\n" + "}" + ) + assert declaration in declarations + assert definition in definitions def test_operator_call_instantiations_keep_scalar_and_optional_tensor_overloads_distinct(