Skip to content

Commit

Permalink
#9767: use reflect library in reflection.hpp
Browse files Browse the repository at this point in the history
  • Loading branch information
arakhmati committed Jun 28, 2024
1 parent d3bebbb commit 97d9fe8
Show file tree
Hide file tree
Showing 9 changed files with 99 additions and 102 deletions.
11 changes: 1 addition & 10 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -96,16 +96,6 @@ if (NOT NUMA_LIBRARY)
message(FATAL_ERROR "NUMA library not found")
endif()


CPMAddPackage(
NAME reflect
GITHUB_REPOSITORY boost-ext/reflect
GIT_TAG v1.1.1
)
add_library(reflect INTERFACE)
target_include_directories(reflect SYSTEM INTERFACE ${reflect_SOURCE_DIR})
add_library(reflect::reflect ALIAS reflect)

############################################################################################################################
# Constructing interface libs for common compiler flags, header directories, and libraries
# These interface libs are linked with PUBLIC scope at lowest common target (tt_metal/common) and at tt_metal_libs level
Expand Down Expand Up @@ -142,6 +132,7 @@ endif()

add_library(metal_header_directories INTERFACE)
target_include_directories(metal_header_directories INTERFACE ${PROJECT_SOURCE_DIR}/tt_metal/hw/inc)
target_include_directories(metal_header_directories SYSTEM INTERFACE ${reflect_SOURCE_DIR})
foreach(lib ${BoostPackages})
target_include_directories(metal_header_directories INTERFACE ${Boost${lib}_SOURCE_DIR}/include)
endforeach()
Expand Down
10 changes: 10 additions & 0 deletions cmake/dependencies.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,13 @@ if (googletest_ADDED)
target_link_libraries(gtest PRIVATE c++ c++abi)
target_link_libraries(gtest_main PRIVATE c++ c++abi)
endif()

############################################################################################################################
# boost-ext reflect : https://github.com/boost-ext/reflect
############################################################################################################################

CPMAddPackage(
NAME reflect
GITHUB_REPOSITORY boost-ext/reflect
GIT_TAG v1.1.1
)
2 changes: 1 addition & 1 deletion tests/ttnn/unit_tests/gtests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ set(TTNN_UNIT_TESTS_SRC

add_executable(unit_tests_ttnn ${TTNN_UNIT_TESTS_SRC})

target_link_libraries(unit_tests_ttnn PUBLIC test_common_libs ttnn_lib tt_metal tt_eager reflect::reflect)
target_link_libraries(unit_tests_ttnn PUBLIC test_common_libs ttnn_lib tt_metal tt_eager)
target_include_directories(unit_tests_ttnn PRIVATE
${UMD_HOME}
${PROJECT_SOURCE_DIR}
Expand Down
2 changes: 1 addition & 1 deletion tt_eager/tt_dnn/op_library/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ set(TT_DNN_SRCS

add_library(tt_dnn OBJECT ${TT_DNN_SRCS})

target_link_libraries(tt_dnn PUBLIC metal_header_directories compiler_flags umd_device reflect::reflect)
target_link_libraries(tt_dnn PUBLIC metal_header_directories compiler_flags umd_device)
target_include_directories(tt_dnn PUBLIC
${UMD_HOME}
${PROJECT_SOURCE_DIR}
Expand Down
18 changes: 7 additions & 11 deletions tt_metal/tools/profiler/op_profiler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#pragma once

#include <filesystem>
#include <reflect>
#include <tuple>
#include <type_traits>

Expand Down Expand Up @@ -274,17 +275,12 @@ inline json get_base_json(
j["op_code"] = opName;

json attributesObj;
constexpr auto& attribute_names = std::decay_t<decltype(operation_attributes)>::attribute_names;
const auto attribute_values = operation_attributes.attribute_values();
[&attributesObj, &attribute_names, &attribute_values]<size_t... Ns>(std::index_sequence<Ns...>) {
(
[&attributesObj, &attribute_names, &attribute_values] {
const auto& attribute_name = std::get<Ns>(attribute_names);
const auto& attribute = std::get<Ns>(attribute_values);
attributesObj[attribute_name] = fmt::format("{}", attribute);
}(),
...);
}(std::make_index_sequence<std::tuple_size_v<std::decay_t<decltype(attribute_names)>>>{});
reflect::for_each(
[&attributesObj, &operation_attributes](auto I) {
attributesObj[std::string{reflect::member_name<I>(operation_attributes)}] =
fmt::format("{}", reflect::get<I>(operation_attributes));
},
operation_attributes);
j["attributes"] = attributesObj;

std::vector<json> input_tensors;
Expand Down
93 changes: 76 additions & 17 deletions tt_metal/tt_stl/reflection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@
#include <experimental/type_traits>
#include <optional>
#include <ostream>
#include <reflect>
#include <set>
#include <string>
#include <tuple>
#include <variant>
#include <vector>

#include "third_party/magic_enum/magic_enum.hpp"

#include "type_name.hpp"

namespace tt {
Expand All @@ -37,9 +37,7 @@ concept IsVariant = requires { typename std::variant_size<T>::type; };

template <IsVariant Variant>
constexpr auto get_active_type_name_in_variant(const Variant& v) {
return std::visit([](auto&& arg) -> std::string_view {
return short_type_name<std::decay_t<decltype(arg)>>;
}, v);
return std::visit([](auto&& arg) -> std::string_view { return short_type_name<std::decay_t<decltype(arg)>>; }, v);
}

// Forward Declare hash_object
Expand Down Expand Up @@ -397,46 +395,100 @@ std::ostream& operator<<(std::ostream& os, const std::set<T>& set) {
return os;
}

template <typename to_visit_t, typename T>
requires std::same_as<std::decay_t<T>, to_visit_t>
template <typename object_t, typename T>
requires std::same_as<std::decay_t<T>, object_t>
constexpr auto visit_object_of_type(auto callback, T&& value) {
callback(value);
}

template <typename to_visit_t, typename T>
template <typename object_t, typename T>
constexpr auto visit_object_of_type(auto callback, const std::optional<T>& value) {
if (value.has_value()) {
visit_object_of_type<to_visit_t>(callback, value.value());
visit_object_of_type<object_t>(callback, value.value());
}
}

template <typename to_visit_t, typename T>
template <typename object_t, typename T>
constexpr auto visit_object_of_type(auto callback, const std::vector<T>& value) {
for (auto& tensor : value) {
visit_object_of_type<to_visit_t>(callback, tensor);
visit_object_of_type<object_t>(callback, tensor);
}
}

template <typename to_visit_t, typename T, auto N>
template <typename object_t, typename T, auto N>
constexpr auto visit_object_of_type(auto callback, const std::array<T, N>& value) {
for (auto& tensor : value) {
visit_object_of_type<to_visit_t>(callback, tensor);
visit_object_of_type<object_t>(callback, tensor);
}
}

template <typename to_visit_t, typename... Ts>
template <typename object_t, typename... Ts>
constexpr auto visit_object_of_type(auto callback, const std::tuple<Ts...>& value) {
constexpr auto num_attributes = sizeof...(Ts);
[&callback, &value]<size_t... Ns>(std::index_sequence<Ns...>) {
(visit_object_of_type<to_visit_t>(callback, std::get<Ns>(value)), ...);
(visit_object_of_type<object_t>(callback, std::get<Ns>(value)), ...);
}(std::make_index_sequence<num_attributes>{});
}

template <typename to_visit_t, typename T>
requires(not std::same_as<std::decay_t<T>, to_visit_t>) and requires { std::decay_t<T>::attribute_names; }
template <typename object_t, typename T>
requires(not std::same_as<std::decay_t<T>, object_t>) and requires { std::decay_t<T>::attribute_names; }
constexpr auto visit_object_of_type(auto callback, T&& object) {
constexpr auto num_attributes = std::tuple_size_v<decltype(std::decay_t<T>::attribute_names)>;
visit_object_of_type<object_t>(callback, object.attribute_values());
}

template <typename object_t, typename T>
requires(not std::same_as<std::decay_t<T>, object_t>) and requires { std::is_aggregate_v<std::decay_t<T>>; }
constexpr auto visit_object_of_type(auto callback, T&& object) {
reflect::for_each(
[&callback, &object](auto I) { visit_object_of_type<object_t>(callback, reflect::get<I>(object)); }, object);
}

template <typename object_t, typename T>
requires std::same_as<std::decay_t<T>, object_t>
constexpr auto get_first_object_of_type(T&& value) {
return std::cref(value);
}

template <typename object_t, typename T>
constexpr auto get_first_object_of_type(const std::optional<T>& value) {
if (value.has_value()) {
const auto& tensor = value.value();
return get_first_object_of_type<object_t>(tensor);
}
}

template <typename object_t, typename T>
constexpr auto get_first_object_of_type(const std::vector<T>& value) {
for (auto& tensor : value) {
return get_first_object_of_type<object_t>(tensor);
}
}

template <typename object_t, typename T, auto N>
constexpr auto get_first_object_of_type(const std::array<T, N>& value) {
for (auto& tensor : value) {
return get_first_object_of_type<object_t>(tensor);
}
}

template <typename object_t, typename... Ts>
constexpr auto get_first_object_of_type(const std::tuple<Ts...>& value) {
constexpr auto num_attributes = sizeof...(Ts);
return get_first_object_of_type<object_t>(std::get<0>(value));
}

template <typename object_t, typename T>
requires (not std::same_as<std::decay_t<T>, object_t>) and requires { std::decay_t<T>::attribute_names; }
constexpr auto get_first_object_of_type(T&& object) {
constexpr auto num_attributes = std::tuple_size_v<decltype(std::decay_t<T>::attribute_names)>;
visit_object_of_type<to_visit_t>(callback, object.attribute_values());
return get_first_object_of_type<object_t>(object.attribute_values());
}

template <typename object_t, typename T>
requires (not std::same_as<std::decay_t<T>, object_t>) and requires { std::is_aggregate_v<std::decay_t<T>>; }
constexpr auto get_first_object_of_type(T&& object) {
return get_first_object_of_type<object_t>(reflect::get<0>(object));
}

} // namespace reflection
Expand Down Expand Up @@ -694,6 +746,13 @@ inline hash_t hash_object(const T& object) noexcept {
} else {
return 0;
}
} else if constexpr (std::is_aggregate_v<T>) {
if constexpr (DEBUG_HASH_OBJECT_FUNCTION) {
fmt::print("Hashing struct {} using reflect library: {}\n", get_type_name<T>(), object);
}
std::size_t hash = 0;
reflect::for_each([&hash, &object](auto I) { hash = hash_objects(hash, reflect::get<I>(object)); }, object);
return hash;
} else {
static_assert(tt::stl::concepts::always_false_v<T>, "Type doesn't support std::hash");
}
Expand Down
2 changes: 1 addition & 1 deletion ttnn/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ set(TTNN_SRCS
add_library(ttnn_lib OBJECT ${TTNN_SRCS})
target_compile_options(ttnn_lib PUBLIC -MP -Wno-int-to-pointer-cast -fno-var-tracking)
target_link_libraries(ttnn_lib
PUBLIC compiler_flags metal_header_directories metal_common_libs reflect::reflect
PUBLIC compiler_flags metal_header_directories metal_common_libs
)
target_include_directories(ttnn_lib PUBLIC
${UMD_HOME}
Expand Down
45 changes: 2 additions & 43 deletions ttnn/cpp/ttnn/device_operation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
#include "tt_stl/concepts.hpp"
#include "tt_stl/reflection.hpp"
#include "tt_stl/unique_any.hpp"
#include <reflect>

namespace ttnn {

Expand Down Expand Up @@ -96,47 +95,6 @@ template <typename... Ts>
return table[i];
}

template <typename T>
requires std::same_as<std::decay_t<T>, Tensor>
constexpr auto get_first_tensor(T&& value) {
return std::cref(value);
}

template <typename T>
constexpr auto get_first_tensor(const std::optional<T>& value) {
if (value.has_value()) {
const auto& tensor = value.value();
return get_first_tensor(tensor);
}
}

template <typename T>
constexpr auto get_first_tensor(const std::vector<T>& value) {
for (auto& tensor : value) {
return get_first_tensor(tensor);
}
}

template <typename T, auto N>
constexpr auto get_first_tensor(const std::array<T, N>& value) {
for (auto& tensor : value) {
return get_first_tensor(tensor);
}
}

template <typename... Ts>
constexpr auto get_first_tensor(const std::tuple<Ts...>& value) {
constexpr auto num_attributes = sizeof...(Ts);
return get_first_tensor(std::get<0>(value));
}

template <typename T>
requires requires { std::decay_t<T>::attribute_names; } and (not std::same_as<std::decay_t<T>, Tensor>)
constexpr auto get_first_tensor(T&& object) {
constexpr auto num_attributes = std::tuple_size_v<decltype(std::decay_t<T>::attribute_names)>;
return get_first_tensor(object.attribute_values());
}

inline const auto USE_FAST_DISPATCH = std::getenv("TT_METAL_SLOW_DISPATCH_MODE") == nullptr;

template <typename device_operation_t>
Expand Down Expand Up @@ -231,7 +189,8 @@ typename device_operation_t::tensor_return_value_t run(
using tensor_return_value_t = typename device_operation_t::tensor_return_value_t;
static_assert(not std::same_as<tensor_return_value_t, void>, "Operation cannot return type cannot be void");

auto device = get_first_tensor(tensor_args).get().device();
// TODO: support the case when tensor args are empty? Or add an overload for that case?
auto device = tt::stl::reflection::get_first_object_of_type<Tensor>(tensor_args).get().device();
auto& program_cache = device->program_cache;

auto program_hash = compute_program_hash<device_operation_t>(operation_attributes, tensor_args);
Expand Down
18 changes: 0 additions & 18 deletions ttnn/cpp/ttnn/operations/eltwise/binary/device/binary_op.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,29 +65,11 @@ struct Binary {
const MemoryConfig memory_config;
const DataType dtype;
std::optional<DeviceComputeKernelConfig> compute_kernel_config;

static constexpr auto attribute_names = std::forward_as_tuple(
"binary_op_type", "in_place", "activations", "memory_config", "dtype", "compute_kernel_config");
const auto attribute_values() const {
return std::forward_as_tuple(
this->binary_op_type,
this->in_place,
this->activations,
this->memory_config,
this->dtype,
this->compute_kernel_config);
}
};
struct tensor_args_t {
const Tensor& input_tensor_a;
const Tensor& input_tensor_b;
std::optional<Tensor> output_tensor;

static constexpr auto attribute_names =
std::forward_as_tuple("input_tensor_a", "input_tensor_b", "output_tensor");
const auto attribute_values() const {
return std::forward_as_tuple(this->input_tensor_a, this->input_tensor_b, this->output_tensor);
}
};
using shape_return_value_t = ttnn::Shape;
using tensor_return_value_t = Tensor;
Expand Down

0 comments on commit 97d9fe8

Please sign in to comment.