diff --git a/include/cudnn_frontend/backend/execution_helpers.h b/include/cudnn_frontend/backend/execution_helpers.h index 32db7f9c1..7138d487a 100644 --- a/include/cudnn_frontend/backend/execution_helpers.h +++ b/include/cudnn_frontend/backend/execution_helpers.h @@ -26,6 +26,9 @@ create_variant_pack(backend_descriptor& variant_pack, void* const* device_ptrs, std::vector const& uids, void* workspace_ptr) { + RETURN_CUDNN_FRONTEND_ERROR_IF(device_ptrs == nullptr && !uids.empty(), + error_code_t::INVALID_VARIANT_PACK, + "device_ptrs must be non-null when uids are provided."); _CUDNN_CHECK_CUDNN_ERROR(detail::set_attribute( variant_pack.get_ptr(), CUDNN_ATTR_VARIANT_PACK_WORKSPACE, CUDNN_TYPE_VOID_PTR, 1, &workspace_ptr)); @@ -59,6 +62,9 @@ create_variant_pack(backend_descriptor& variant_pack, std::vector const& override_uids, std::vector> const& override_shapes, std::vector> const& override_strides) { + RETURN_CUDNN_FRONTEND_ERROR_IF(device_ptrs == nullptr && !uids.empty(), + error_code_t::INVALID_VARIANT_PACK, + "device_ptrs must be non-null when uids are provided."); auto cudnn_ver_error = error_t{error_code_t::GRAPH_NOT_SUPPORTED, "Dynamic shapes requires cuDNN v9.18.0"}; NV_CUDNN_FE_DYNAMIC_CHECK_CUDNN_BACKEND_VERSION(91800, cudnn_ver_error); diff --git a/include/cudnn_frontend/graph_interface.h b/include/cudnn_frontend/graph_interface.h index c3d33a858..32efdf6d8 100644 --- a/include/cudnn_frontend/graph_interface.h +++ b/include/cudnn_frontend/graph_interface.h @@ -1624,6 +1624,14 @@ class Graph : public ICudnn, public INode { #ifndef CUDNN_FRONTEND_SKIP_JSON_LIB json j = json::from_ubjson(data); + // Clear deserialize-owned containers so a re-deserialize on the same Graph + // does not feed prepare_variant_pack_template() with stale entries from a + // prior deserialize(handle, old_data). + deserialized_tensor_properties.clear(); + deserialized_pass_by_value.clear(); + deserialized_workspace_modifications.clear(); + tensors_to_dump.clear(); + if (j.contains("graph_uid") && !j["graph_uid"].is_null()) { graph_uid = j["graph_uid"].get(); } @@ -1676,6 +1684,11 @@ class Graph : public ICudnn, public INode { cached_pass_by_value = deserialized_pass_by_value; cached_workspace_modifications = deserialized_workspace_modifications; + // Reset prep state in case this Graph is being re-deserialized; otherwise the + // eager prep below would early-return with the old slot layout. + varpack_prep_state->prepared.store(false, std::memory_order_release); + varpack_template = {}; + // Eager prep, matching what build_plans() does for fresh-build graphs. CHECK_CUDNN_FRONTEND_ERROR(prepare_variant_pack_template()); @@ -2069,16 +2082,14 @@ class Graph : public ICudnn, public INode { VarpackPrepStateBox(VarpackPrepStateBox &&) noexcept = default; VarpackPrepStateBox & operator=(VarpackPrepStateBox &&) noexcept = default; - VarpackPrepStateBox(VarpackPrepStateBox const &other) : ptr(std::make_unique()) { - if (other.ptr) { - ptr->prepared.store(other.ptr->prepared.load(std::memory_order_acquire), std::memory_order_release); - } - } + // Copy semantics: never copy the prepared flag. The cached template_ptrs + // store raw addresses into the source Graph's pass-by-value storage; a + // copied Graph must rebuild its own template on first use. + VarpackPrepStateBox(VarpackPrepStateBox const & /*other*/) : ptr(std::make_unique()) {} VarpackPrepStateBox & operator=(VarpackPrepStateBox const &other) { if (this != &other) { - VarpackPrepStateBox tmp(other); - ptr.swap(tmp.ptr); + ptr = std::make_unique(); } return *this; } diff --git a/include/cudnn_frontend/plans.h b/include/cudnn_frontend/plans.h index df674dd4a..64f3f05f1 100644 --- a/include/cudnn_frontend/plans.h +++ b/include/cudnn_frontend/plans.h @@ -27,8 +27,9 @@ execute(cudnnHandle_t handle, std::vector const& override_uids, std::vector> const& override_shapes, std::vector> const& override_strides) { - // TODO: below line fails with MSVC. warning C4127: conditional expression is constant - // RETURN_CUDNN_FRONTEND_ERROR_IF(!plan, error_code_t::GRAPH_EXECUTION_FAILED, "No plan found to execute!!"); + if (plan == nullptr) { + return {error_code_t::GRAPH_EXECUTION_FAILED, "No plan found to execute!"}; + } CUDNN_FE_LOG_LABEL_ENDL("INFO: Executing " << plan->getTag() << "..."); backend_descriptor variant_pack_descriptor(CUDNN_BACKEND_VARIANT_PACK_DESCRIPTOR); @@ -51,8 +52,9 @@ execute(cudnnHandle_t handle, std::vector& device_ptrs, std::vector const& uids, void* workspace_ptr) { - // TODO: below line fails with MSVC. warning C4127: conditional expression is constant - // RETURN_CUDNN_FRONTEND_ERROR_IF(!plan, error_code_t::GRAPH_EXECUTION_FAILED, "No plan found to execute!!"); + if (plan == nullptr) { + return {error_code_t::GRAPH_EXECUTION_FAILED, "No plan found to execute!"}; + } CUDNN_FE_LOG_LABEL_ENDL("INFO: Executing " << plan->getTag() << "..."); backend_descriptor variant_pack_descriptor(CUDNN_BACKEND_VARIANT_PACK_DESCRIPTOR); @@ -76,6 +78,9 @@ execute(cudnnHandle_t handle, void* const* device_ptrs, std::vector const& uids, void* workspace_ptr) { + if (plan == nullptr) { + return {error_code_t::GRAPH_EXECUTION_FAILED, "No plan found to execute!"}; + } CUDNN_FE_LOG_LABEL_ENDL("INFO: Executing " << plan->getTag() << "..."); backend_descriptor variant_pack_descriptor(CUDNN_BACKEND_VARIANT_PACK_DESCRIPTOR); @@ -99,6 +104,9 @@ execute(cudnnHandle_t handle, std::vector const& override_uids, std::vector> const& override_shapes, std::vector> const& override_strides) { + if (plan == nullptr) { + return {error_code_t::GRAPH_EXECUTION_FAILED, "No plan found to execute!"}; + } CUDNN_FE_LOG_LABEL_ENDL("INFO: Executing " << plan->getTag() << "..."); backend_descriptor variant_pack_descriptor(CUDNN_BACKEND_VARIANT_PACK_DESCRIPTOR);