diff --git a/CMakeLists.txt b/CMakeLists.txt index 357f7969b..33ad50028 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,11 +6,18 @@ option(CUDNN_FRONTEND_SKIP_JSON_LIB "Defines whether FE should not include nlohm option(CUDNN_FRONTEND_BUILD_SAMPLES "Defines if samples are built or not." ON) option(CUDNN_FRONTEND_BUILD_TESTS "Defines if unittests are built or not." ON) option(CUDNN_FRONTEND_BUILD_PYTHON_BINDINGS "Defines if python bindings are built or not." OFF) +option(CUDNN_FRONTEND_ENABLE_RTTI "Build in-tree targets with RTTI. Off by default so the headers stay compilable for consumers that disable it." OFF) if(MSVC OR MSYS OR MINGW) add_compile_options(/W4 /WX) + if(NOT CUDNN_FRONTEND_ENABLE_RTTI) + add_compile_options(/GR-) + endif() else() add_compile_options(-Wall -Wextra -Wpedantic -Werror -Wno-error=attributes -Wno-attributes -Wno-error=unused-function -Wno-unused-function) + if(NOT CUDNN_FRONTEND_ENABLE_RTTI) + add_compile_options(-fno-rtti) + endif() endif() add_library(cudnn_frontend INTERFACE) diff --git a/include/cudnn_frontend/graph_interface.h b/include/cudnn_frontend/graph_interface.h index be54b51d8..3e36cb0ec 100644 --- a/include/cudnn_frontend/graph_interface.h +++ b/include/cudnn_frontend/graph_interface.h @@ -419,15 +419,13 @@ class Graph : public ICudnn, public INode { // Register an OSS NVRTC engine for SDPA by extracting tensor metadata from the SDPA node's attributes error_t register_oss_engine_() { - // Find the SDPA node in the graph's sub_nodes via dynamic_cast + // Find the SDPA node in the graph's sub_nodes. Uses the virtual get_sdpa_attributes() + // accessor rather than dynamic_cast so this header compiles under -fno-rtti / /GR-. + // Covers both CompositeSDPANode and UnifiedSDPANode, which share SDPANodeBase. SDPA_attributes const *sdpa_attrs = nullptr; for (auto const &sub_node : sub_nodes) { - if (auto *composite = dynamic_cast(sub_node.get())) { - sdpa_attrs = &composite->attributes; - break; - } - if (auto *unified = dynamic_cast(sub_node.get())) { - sdpa_attrs = &unified->attributes; + if (auto const *attrs = sub_node->get_sdpa_attributes()) { + sdpa_attrs = attrs; break; } } @@ -539,11 +537,14 @@ class Graph : public ICudnn, public INode { std::shared_ptr swish_output; for (size_t i = 0; i + 1 < sub_nodes.size(); ++i) { - auto *rmsnorm_node = dynamic_cast(sub_nodes[i].get()); - if (!rmsnorm_node) continue; - - auto *pointwise_node = dynamic_cast(sub_nodes[i + 1].get()); - if (!pointwise_node) continue; + // getType() + static_cast rather than dynamic_cast so this header compiles under + // -fno-rtti / /GR-. RMSNORM and POINTWISE are distinct Type values, so this is an + // exact substitute for the type-check the dynamic_casts performed. + if (sub_nodes[i]->getType() != Type::RMSNORM) continue; + auto *rmsnorm_node = static_cast(sub_nodes[i].get()); + + if (sub_nodes[i + 1]->getType() != Type::POINTWISE) continue; + auto *pointwise_node = static_cast(sub_nodes[i + 1].get()); if (pointwise_node->attributes.get_mode() != PointwiseMode_t::SWISH_FWD) continue; diff --git a/include/cudnn_frontend/node/scaled_dot_product_flash_attention.h b/include/cudnn_frontend/node/scaled_dot_product_flash_attention.h index 79f91a554..942b5c9bc 100644 --- a/include/cudnn_frontend/node/scaled_dot_product_flash_attention.h +++ b/include/cudnn_frontend/node/scaled_dot_product_flash_attention.h @@ -137,6 +137,11 @@ class SDPANodeBase : public NodeCRTP { SDPANodeBase(SDPA_attributes&& attributes_, detail::Context const& context) : NodeCRTP(context), attributes(std::move(attributes_)) {} + SDPA_attributes const* + get_sdpa_attributes() const override { + return &attributes; + } + bool is_paged_v() const { auto page_table_v_it = attributes.inputs.find(input_names::Page_table_V); diff --git a/include/cudnn_frontend/node_interface.h b/include/cudnn_frontend/node_interface.h index dad9b5987..8e2ef8ac2 100644 --- a/include/cudnn_frontend/node_interface.h +++ b/include/cudnn_frontend/node_interface.h @@ -402,6 +402,14 @@ class INode { virtual Type getType() = 0; + // Returns this node's SDPA attributes if it is an SDPA node, nullptr otherwise. + // Provides an RTTI-free alternative to dynamic_cast for SDPA node discovery so that + // these headers compile under -fno-rtti (GCC/Clang) and /GR- (MSVC). + virtual SDPA_attributes const* + get_sdpa_attributes() const { + return nullptr; + } + virtual std::pair> override_heuristics_query() const { return {-1, {}}; diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index f0de87734..6792a4bd3 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -72,6 +72,14 @@ target_link_libraries(_compiled_module PRIVATE pybind11::headers) target_compile_features(_compiled_module PRIVATE cxx_std_20) +# pybind11's type registry is typeid-based, so this module requires RTTI even when +# CUDNN_FRONTEND_ENABLE_RTTI is off for the rest of the build. +if(MSVC) + target_compile_options(_compiled_module PRIVATE /GR) +else() + target_compile_options(_compiled_module PRIVATE -frtti) +endif() + target_include_directories( _compiled_module PRIVATE $