/* * Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #pragma once #include #include #include #include #include #include #include "cudnn_frontend_utils.h" namespace cudnn_frontend { /// /// Resample Descriptor Class /// This class tells the properties of the Resample operation /// Properties: /// /// Use ResampleDescBuilder_v8 to build this class. /// Describe returns a string describing the Resample operation /// class ResampleDesc_v8 : public BackendDescriptor { public: friend class ResampleDescBuilder_v8; std::string describe() const override { std::stringstream ss; char sep = ','; #ifndef CUDNN_FRONTEND_SKIP_JSON_LIB ss << "CUDNN_BACKEND_RESAMPLE_DESCRIPTOR: " << "Compute Type: " << json{computeType} << ", Resample Mode: " << json{resample_mode} << ", Spatial Dimensions: " << spatialDim << ", Nan Propagation: " << std::to_string(nanOpt) << ", Padding Mode: " << json{padding_mode}; #else ss << "CUDNN_BACKEND_RESAMPLE_DESCRIPTOR: " << "Compute Type: " << int(computeType) << ", Resample Mode: " << int(resample_mode) << ", Spatial Dimensions: " << spatialDim << ", Nan Propagation: " << std::to_string(nanOpt) << ", Padding Mode: " << int(padding_mode); #endif ss << ", WindowDim: ["; for (auto i = 0; i < spatialDim; i++) { ss << '(' << windowDim[i].numerator << sep << windowDim[i].denominator << ')' << sep; } ss << "]"; ss << ", prePadding: ["; for (auto i = 0; i < spatialDim; i++) { ss << '(' << prePadding[i].numerator << sep << prePadding[i].denominator << ')' << sep; } ss << "]"; ss << ", postPadding: ["; for (auto i = 0; i < spatialDim; i++) { ss << '(' << postPadding[i].numerator << sep << postPadding[i].denominator << ')' << sep; } ss << "]"; ss << ", stride: [ "; for (auto i = 0; i < spatialDim; i++) { ss << '(' << stride[i].numerator << sep << stride[i].denominator << ')' << sep; } ss << "]"; return ss.str(); } ResampleDesc_v8(ResampleDesc_v8 &&from) = default; ResampleDesc_v8 & operator=(ResampleDesc_v8 &&) = default; ~ResampleDesc_v8() = default; /** @defgroup ResampleDescBuilder_v8 * Get individual property of ResampleDesc_v8 class * @{ */ DataType_t getComputeType() const { return computeType; } int64_t getSpatialDimCount() const { return spatialDim; } cudnnNanPropagation_t getNanOpt() const { return nanOpt; } ResampleMode_t getMode() const { return resample_mode; } PaddingMode_t getPaddingMode() const { return padding_mode; } cudnnFraction_t const * getSpatialStride() const { return stride; } cudnnFraction_t const * getPrePadding() const { return prePadding; } cudnnFraction_t const * getPostPadding() const { return postPadding; } cudnnFraction_t const * getWindowDim() const { return windowDim; } /** @} */ private: ResampleDesc_v8() = default; ResampleDesc_v8(ResampleDesc_v8 const &) = delete; ResampleDesc_v8 & operator=(ResampleDesc_v8 const &) = delete; // default values for attributes DataType_t computeType = DataType_t::FLOAT; cudnnNanPropagation_t nanOpt = CUDNN_PROPAGATE_NAN; ResampleMode_t resample_mode = ResampleMode_t::NOT_SET; PaddingMode_t padding_mode = PaddingMode_t::NOT_SET; int64_t spatialDim = 0; // Shape attributes cudnnFraction_t windowDim[CUDNN_DIM_MAX] = {{0, 1}, {0, 1}}; cudnnFraction_t prePadding[CUDNN_DIM_MAX] = {{0, 1}, {0, 1}}; cudnnFraction_t postPadding[CUDNN_DIM_MAX] = {{0, 1}, {0, 1}}; cudnnFraction_t stride[CUDNN_DIM_MAX] = {{0, 1}, {0, 1}}; }; /// /// ResampleDescBuilder_v8 Class /// Helper class used to build ResampleDesc_v8 class class ResampleDescBuilder_v8 { public: /** @defgroup ResampleDescBuilder_v8 * Set individual property of ResampleDesc_v8 class * @{ */ //! Set compute type for the Resample Descriptor auto setComputeType(DataType_t data_type) -> ResampleDescBuilder_v8 & { m_resampleDesc.computeType = data_type; return *this; } // To be deprecated in v1.0. auto setComputeType(cudnnDataType_t data_type_) -> ResampleDescBuilder_v8 & { m_resampleDesc.computeType = detail::convert_from_cudnn_type(data_type_); return *this; } //! Set nan propagation mode for the Resample Operation auto setNanPropagation(cudnnNanPropagation_t nanOpt_) -> ResampleDescBuilder_v8 & { m_resampleDesc.nanOpt = nanOpt_; return *this; } //! (Overloaded) Set post padding for the Resample Operation with cudnnFraction_t auto setPostPadding(int64_t count, cudnnFraction_t const *arr) -> ResampleDescBuilder_v8 & { // TODO: check the provided array count against the stored spatial dimension count. std::copy(arr, arr + count, m_resampleDesc.postPadding); return *this; } //! (Overloaded) Set pre padding for the Resample Operation with cudnnFraction_t auto setPrePadding(int64_t count, cudnnFraction_t const *arr) -> ResampleDescBuilder_v8 & { // TODO: check the provided array count against the stored spatial dimension count. std::copy(arr, arr + count, m_resampleDesc.prePadding); return *this; } //! (Overloaded) Set stride for the Resample Operation with cudnnFraction_t auto setSpatialStride(int64_t count, cudnnFraction_t const *arr) -> ResampleDescBuilder_v8 & { // TODO: check the provided array count against the stored spatial dimension count. std::copy(arr, arr + count, m_resampleDesc.stride); return *this; } //! Set resample mode for the Resample Operation // To be deprecated. Please use setResampleMode(cudnn_frontend::ResampleMode_t). auto setResampleMode(cudnnResampleMode_t const mode_) -> ResampleDescBuilder_v8 & { detail::convert_from_cudnn_type(mode_, m_resampleDesc.resample_mode); return *this; } //! (Overloaded) Set window dim for the Resample Operation with cudnnFraction_t auto setSpatialDim(int64_t count, cudnnFraction_t const *arr) -> ResampleDescBuilder_v8 & { // TODO: check the provided array count against the stored spatial dimension count. m_resampleDesc.spatialDim = count; std::copy(arr, arr + count, m_resampleDesc.windowDim); return *this; } //! Set padding mode for the Resample Operation // To be deprecated. Please use setPaddingMode(cudnn_frontend::PaddingMode_t). auto setPaddingMode(cudnnPaddingMode_t const padding_mode) -> ResampleDescBuilder_v8 & { detail::convert_from_cudnn_type(padding_mode, m_resampleDesc.padding_mode); return *this; } //! Set padding mode for the Resample Operation auto setPaddingMode(PaddingMode_t const padding_mode) -> ResampleDescBuilder_v8 & { m_resampleDesc.padding_mode = padding_mode; return *this; } //! Set resample mode for the Resample Operation auto setResampleMode(ResampleMode_t const mode) -> ResampleDescBuilder_v8 & { m_resampleDesc.resample_mode = mode; return *this; } //! (Overloaded) Set post padding for the Resample Operation with int64_t auto setPostPadding(int64_t count, int64_t const *arr) -> ResampleDescBuilder_v8 & { // TODO: check the provided array count against the stored spatial dimension count. for (int i = 0; i < count; i++) { m_resampleDesc.postPadding[i].numerator = arr[i]; m_resampleDesc.postPadding[i].denominator = 1; } return *this; } //! (Overloaded) Set pre padding for the Resample Operation with int64_t auto setPrePadding(int64_t count, int64_t const *arr) -> ResampleDescBuilder_v8 & { // TODO: check the provided array count against the stored spatial dimension count. for (int i = 0; i < count; i++) { m_resampleDesc.prePadding[i].numerator = arr[i]; m_resampleDesc.prePadding[i].denominator = 1; } return *this; } //! (Overloaded) Set stride for the Resample Operation with int64_t auto setSpatialStride(int64_t count, int64_t const *arr) -> ResampleDescBuilder_v8 & { // TODO: check the provided array count against the stored spatial dimension count. for (int i = 0; i < count; i++) { m_resampleDesc.stride[i].numerator = arr[i]; m_resampleDesc.stride[i].denominator = 1; } return *this; } //! (Overloaded) Set window dim for the Resample Operation with int64_t auto setSpatialDim(int64_t count, int64_t const *arr) -> ResampleDescBuilder_v8 & { // TODO: check the provided array count against the stored spatial dimension count. m_resampleDesc.spatialDim = count; for (int i = 0; i < count; i++) { m_resampleDesc.windowDim[i].numerator = arr[i]; m_resampleDesc.windowDim[i].denominator = 1; } return *this; } /** @} */ //! constructs the ResampleDesc_v8 by calling the cudnn API //! Throws the appropriate error message ResampleDesc_v8 && build() { // Sanity check if non-default fields have been set correctly. if (m_resampleDesc.spatialDim < 0) { set_error_and_throw_exception(&m_resampleDesc, CUDNN_STATUS_BAD_PARAM, "CUDNN_BACKEND_RESAMPLE_DESCRIPTOR: Check and Set the spatialDim field"); return std::move(m_resampleDesc); }; // Create a descriptor. Memory allocation happens here. auto status = m_resampleDesc.initialize_managed_backend_pointer(CUDNN_BACKEND_RESAMPLE_DESCRIPTOR); if (status != CUDNN_STATUS_SUCCESS) { set_error_and_throw_exception( &m_resampleDesc, status, "CUDNN_BACKEND_RESAMPLE_DESCRIPTOR: cudnnCreate Failed"); return std::move(m_resampleDesc); } // Once Created lets set the descriptor parameters. ::cudnnResampleMode_t cudnn_resample_mode; status = detail::convert_to_cudnn_type(m_resampleDesc.resample_mode, cudnn_resample_mode); if (status != CUDNN_STATUS_SUCCESS) { set_error_and_throw_exception( &m_resampleDesc, status, "CUDNN_BACKEND_RESAMPLE_DESCRIPTOR: SetAttribute CUDNN_ATTR_RESAMPLE_MODE Failed"); return std::move(m_resampleDesc); } status = detail::set_attribute(m_resampleDesc.pointer->get_backend_descriptor(), CUDNN_ATTR_RESAMPLE_MODE, CUDNN_TYPE_RESAMPLE_MODE, 1, &cudnn_resample_mode); if (status != CUDNN_STATUS_SUCCESS) { set_error_and_throw_exception( &m_resampleDesc, status, "CUDNN_BACKEND_RESAMPLE_DESCRIPTOR: SetAttribute CUDNN_ATTR_RESAMPLE_MODE Failed"); return std::move(m_resampleDesc); } cudnnDataType_t cudnn_data_type; status = detail::convert_to_cudnn_type(m_resampleDesc.computeType, cudnn_data_type); if (status != CUDNN_STATUS_SUCCESS) { set_error_and_throw_exception( &m_resampleDesc, status, "CUDNN_BACKEND_RESAMPLE_DESCRIPTOR: SetAttribute CUDNN_ATTR_RESAMPLE_COMP_TYPE Failed"); return std::move(m_resampleDesc); } status = detail::set_attribute(m_resampleDesc.pointer->get_backend_descriptor(), CUDNN_ATTR_RESAMPLE_COMP_TYPE, CUDNN_TYPE_DATA_TYPE, 1, &cudnn_data_type); if (status != CUDNN_STATUS_SUCCESS) { set_error_and_throw_exception( &m_resampleDesc, status, "CUDNN_BACKEND_RESAMPLE_DESCRIPTOR: SetAttribute CUDNN_ATTR_RESAMPLE_COMP_TYPE Failed"); return std::move(m_resampleDesc); } status = detail::set_attribute(m_resampleDesc.pointer->get_backend_descriptor(), CUDNN_ATTR_RESAMPLE_NAN_PROPAGATION, CUDNN_TYPE_NAN_PROPOGATION, 1, &(m_resampleDesc.nanOpt)); if (status != CUDNN_STATUS_SUCCESS) { set_error_and_throw_exception( &m_resampleDesc, status, "CUDNN_BACKEND_RESAMPLE_DESCRIPTOR: SetAttribute CUDNN_ATTR_RESAMPLE_NAN_PROPAGATION Failed"); return std::move(m_resampleDesc); } cudnnPaddingMode_t cudnn_padding_mode; status = detail::convert_to_cudnn_type(m_resampleDesc.padding_mode, cudnn_padding_mode); if (status != CUDNN_STATUS_SUCCESS) { set_error_and_throw_exception( &m_resampleDesc, status, "CUDNN_BACKEND_RESAMPLE_DESCRIPTOR: SetAttribute CUDNN_ATTR_RESAMPLE_PADDING_MODE Failed"); return std::move(m_resampleDesc); } status = detail::set_attribute(m_resampleDesc.pointer->get_backend_descriptor(), CUDNN_ATTR_RESAMPLE_PADDING_MODE, CUDNN_TYPE_PADDING_MODE, 1, &cudnn_padding_mode); if (status != CUDNN_STATUS_SUCCESS) { set_error_and_throw_exception( &m_resampleDesc, status, "CUDNN_BACKEND_RESAMPLE_DESCRIPTOR: SetAttribute CUDNN_ATTR_RESAMPLE_PADDING_MODE Failed"); return std::move(m_resampleDesc); } status = detail::set_attribute(m_resampleDesc.pointer->get_backend_descriptor(), CUDNN_ATTR_RESAMPLE_SPATIAL_DIMS, CUDNN_TYPE_INT64, 1, &(m_resampleDesc.spatialDim)); if (status != CUDNN_STATUS_SUCCESS) { set_error_and_throw_exception( &m_resampleDesc, status, "CUDNN_BACKEND_RESAMPLE_DESCRIPTOR: SetAttribute CUDNN_ATTR_RESAMPLE_SPATIAL_DIMS Failed"); return std::move(m_resampleDesc); } status = detail::set_attribute(m_resampleDesc.pointer->get_backend_descriptor(), CUDNN_ATTR_RESAMPLE_WINDOW_DIMS, CUDNN_TYPE_FRACTION, m_resampleDesc.spatialDim, m_resampleDesc.windowDim); if (status != CUDNN_STATUS_SUCCESS) { set_error_and_throw_exception( &m_resampleDesc, status, "CUDNN_BACKEND_RESAMPLE_DESCRIPTOR: SetAttribute CUDNN_ATTR_RESAMPLE_WINDOW_DIMS Failed"); return std::move(m_resampleDesc); } status = detail::set_attribute(m_resampleDesc.pointer->get_backend_descriptor(), CUDNN_ATTR_RESAMPLE_PRE_PADDINGS, CUDNN_TYPE_FRACTION, m_resampleDesc.spatialDim, m_resampleDesc.prePadding); if (status != CUDNN_STATUS_SUCCESS) { set_error_and_throw_exception( &m_resampleDesc, status, "CUDNN_BACKEND_RESAMPLE_DESCRIPTOR: SetAttribute CUDNN_ATTR_RESAMPLE_PRE_PADDINGS Failed"); return std::move(m_resampleDesc); } status = detail::set_attribute(m_resampleDesc.pointer->get_backend_descriptor(), CUDNN_ATTR_RESAMPLE_POST_PADDINGS, CUDNN_TYPE_FRACTION, m_resampleDesc.spatialDim, m_resampleDesc.postPadding); if (status != CUDNN_STATUS_SUCCESS) { set_error_and_throw_exception( &m_resampleDesc, status, "CUDNN_BACKEND_RESAMPLE_DESCRIPTOR: SetAttribute CUDNN_ATTR_RESAMPLE_POST_PADDINGS Failed"); return std::move(m_resampleDesc); } status = detail::set_attribute(m_resampleDesc.pointer->get_backend_descriptor(), CUDNN_ATTR_RESAMPLE_STRIDES, CUDNN_TYPE_FRACTION, m_resampleDesc.spatialDim, m_resampleDesc.stride); if (status != CUDNN_STATUS_SUCCESS) { set_error_and_throw_exception( &m_resampleDesc, status, "CUDNN_BACKEND_RESAMPLE_DESCRIPTOR: SetAttribute CUDNN_ATTR_RESAMPLE_STRIDES Failed"); return std::move(m_resampleDesc); } // Finalizing the descriptor status = detail::finalize(m_resampleDesc.pointer->get_backend_descriptor()); if (status != CUDNN_STATUS_SUCCESS) { set_error_and_throw_exception( &m_resampleDesc, status, "CUDNN_BACKEND_RESAMPLE_DESCRIPTOR: cudnnFinalize Failed"); return std::move(m_resampleDesc); } CUDNN_FE_LOG_LABEL_ENDL(m_resampleDesc); return std::move(m_resampleDesc); } explicit ResampleDescBuilder_v8() = default; ~ResampleDescBuilder_v8() = default; ResampleDescBuilder_v8(ResampleDescBuilder_v8 &&) = delete; ResampleDescBuilder_v8(ResampleDescBuilder_v8 const &) = delete; ResampleDescBuilder_v8 & operator=(ResampleDescBuilder_v8 const &) = delete; private: ResampleDesc_v8 m_resampleDesc; }; } // namespace cudnn_frontend