代码评注赛:想不到名字了所以随便看一下队名到底能有多长队PR #12
|
|
@ -23,80 +23,124 @@ namespace mindspore {
|
|||
namespace abstract {
|
||||
class Evaluator;
|
||||
class AnalysisEngine;
|
||||
// Function to create an AbstractFunction from a list of AbstractFuncAtomPtr.
|
||||
AbstractFunctionPtr AbstractFunction::MakeAbstractFunction(const AbstractFuncAtomPtrList &func_list) {
|
||||
// Check the size of the input list.
|
||||
if (func_list.size() == 1) {
|
||||
// If there is only one element in the list, return that element.
|
||||
return func_list[0];
|
||||
}
|
||||
// If there are multiple elements in the list, create an AbstractFuncUnion.
|
||||
return std::make_shared<AbstractFuncUnion>(func_list);
|
||||
}
|
||||
|
||||
// Join two AbstractFunctions into a single AbstractFunction.
|
||||
AbstractFunctionPtr AbstractFuncAtom::Join(const AbstractFunctionPtr &other) {
|
||||
// Check if the 'other' AbstractFunction pointer is not null.
|
||||
MS_EXCEPTION_IF_NULL(other);
|
||||
|
||||
// Get a shared pointer to the current AbstractFuncAtom.
|
||||
auto this_func = shared_from_base<AbstractFuncAtom>();
|
||||
|
||||
if (other->isa<AbstractFuncAtom>()) {
|
||||
// If 'other' is an AbstractFuncAtom, check if the two AbstractFuncAtoms are equal.
|
||||
if (*this_func == *other) {
|
||||
// If they are equal, return the current AbstractFuncAtom.
|
||||
return this_func;
|
||||
}
|
||||
// If they are not equal, create an AbstractFuncUnion with both AbstractFuncAtoms.
|
||||
return std::make_shared<AbstractFuncUnion>(this_func, other);
|
||||
}
|
||||
|
||||
// If 'other' is an AbstractFuncUnion, check if it is a superset of the current AbstractFuncAtom.
|
||||
auto other_union = dyn_cast<AbstractFuncUnion>(other);
|
||||
MS_EXCEPTION_IF_NULL(other_union);
|
||||
|
||||
if (other_union->IsSuperSet(this_func)) {
|
||||
// If 'other_union' is a superset of the current AbstractFuncAtom, return 'other'.
|
||||
return other;
|
||||
}
|
||||
|
||||
// If 'other_union' is not a superset, create an AbstractFuncUnion with both AbstractFunctions.
|
||||
return std::make_shared<AbstractFuncUnion>(this_func, other);
|
||||
}
|
||||
|
||||
// Visit function to perform an operation on the current AbstractFuncAtom.
|
||||
void AbstractFuncAtom::Visit(std::function<void(const AbstractFuncAtomPtr &)> visit_func) const {
|
||||
// Call the 'visit_func' function with the current AbstractFuncAtom.
|
||||
visit_func(const_cast<AbstractFuncAtom *>(this)->shared_from_base<AbstractFuncAtom>());
|
||||
}
|
||||
|
||||
bool AbstractFuncAtom::operator==(const AbstractFunction &other) const { return this == &other; }
|
||||
// Equality comparison operator for AbstractFunction.
|
||||
bool AbstractFuncAtom::operator==(const AbstractFunction &other) const {
|
||||
// Check if the current AbstractFunction is equal to 'other' by comparing their addresses.
|
||||
return this == &other;
|
||||
}
|
||||
|
||||
AbstractFuncUnion::AbstractFuncUnion(const AbstractFuncAtomPtrList &func_list) { func_list_ = func_list; }
|
||||
// Constructor for AbstractFuncUnion with a list of AbstractFuncAtom pointers.
|
||||
AbstractFuncUnion::AbstractFuncUnion(const AbstractFuncAtomPtrList &func_list) {
|
||||
func_list_ = func_list;
|
||||
}
|
||||
|
||||
// Constructor for AbstractFuncUnion with two AbstractFunctions.
|
||||
AbstractFuncUnion::AbstractFuncUnion(const AbstractFunctionPtr &first, const AbstractFunctionPtr &second) {
|
||||
AbstractFuncAtomPtrList new_func_list;
|
||||
auto build_func_list = [&new_func_list](const AbstractFuncAtomPtr &func) { new_func_list.push_back(func); };
|
||||
auto build_func_list = [&new_func_list](const AbstractFuncAtomPtr &func) {
|
||||
new_func_list.push_back(func);
|
||||
};
|
||||
|
||||
// Check if the input AbstractFunctions are not null.
|
||||
MS_EXCEPTION_IF_NULL(first);
|
||||
MS_EXCEPTION_IF_NULL(second);
|
||||
|
||||
// Visit both AbstractFunctions and build the list.
|
||||
first->Visit(build_func_list);
|
||||
second->Visit(build_func_list);
|
||||
|
||||
func_list_ = new_func_list;
|
||||
}
|
||||
|
||||
// Convert AbstractFuncUnion to a string.
|
||||
std::string AbstractFuncUnion::ToString() const {
|
||||
std::ostringstream buffer;
|
||||
buffer << "AbstractFuncUnion({";
|
||||
int64_t i = 0;
|
||||
|
||||
for (const auto &func : func_list_) {
|
||||
MS_EXCEPTION_IF_NULL(func);
|
||||
buffer << "[" << i << "]: " << func->ToString() << ", ";
|
||||
i++;
|
||||
}
|
||||
|
||||
buffer << "})";
|
||||
return buffer.str();
|
||||
}
|
||||
|
||||
// Convert AbstractFuncUnion to a string, optionally in a verbose mode.
|
||||
std::string AbstractFuncUnion::ToString(bool verbose) const {
|
||||
if (verbose) {
|
||||
return ToString();
|
||||
}
|
||||
|
||||
std::ostringstream buffer;
|
||||
buffer << type_name() << "({";
|
||||
size_t i = 0;
|
||||
|
||||
for (const auto &func : func_list_) {
|
||||
MS_EXCEPTION_IF_NULL(func);
|
||||
buffer << func->ToString(false);
|
||||
i++;
|
||||
|
||||
if (i < func_list_.size()) {
|
||||
buffer << ", ";
|
||||
}
|
||||
}
|
||||
|
||||
buffer << "})";
|
||||
return buffer.str();
|
||||
}
|
||||
|
||||
// Check if the current AbstractFuncUnion is a superset of another AbstractFunction.
|
||||
bool AbstractFuncUnion::IsSuperSet(const AbstractFunctionPtr &other) {
|
||||
MS_EXCEPTION_IF_NULL(other);
|
||||
std::vector<bool> is_in_list;
|
||||
|
|
@ -107,61 +151,90 @@ bool AbstractFuncUnion::IsSuperSet(const AbstractFunctionPtr &other) {
|
|||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
// Visit 'other' AbstractFunction and build a list of whether each element is in the current AbstractFuncUnion.
|
||||
other->Visit(build_in_list);
|
||||
|
||||
// Check if all elements in the 'is_in_list' are true.
|
||||
return std::all_of(is_in_list.begin(), is_in_list.end(), [](bool is_in) { return is_in; });
|
||||
}
|
||||
|
||||
// Join two AbstractFunctions into a single AbstractFunction.
|
||||
AbstractFunctionPtr AbstractFuncUnion::Join(const AbstractFunctionPtr &other) {
|
||||
// Get a shared pointer to the current AbstractFunction.
|
||||
auto this_func = shared_from_base<AbstractFunction>();
|
||||
MS_EXCEPTION_IF_NULL(other);
|
||||
|
||||
if (other->isa<AbstractFuncAtom>()) {
|
||||
// If 'other' is an AbstractFuncAtom, check if the current AbstractFuncUnion is a superset of 'other'.
|
||||
if (IsSuperSet(other)) {
|
||||
// If it is a superset, return the current AbstractFunction.
|
||||
return this_func;
|
||||
}
|
||||
// If not a superset, create an AbstractFuncUnion with both AbstractFunctions.
|
||||
return std::make_shared<AbstractFuncUnion>(this_func, other);
|
||||
}
|
||||
|
||||
// If 'other' is an AbstractFuncUnion, check if it is a superset of the current AbstractFunction.
|
||||
auto other_union = dyn_cast<AbstractFuncUnion>(other);
|
||||
MS_EXCEPTION_IF_NULL(other_union);
|
||||
|
||||
if (other_union->IsSuperSet(this_func)) {
|
||||
// If it is a superset, return 'other'.
|
||||
return other;
|
||||
}
|
||||
|
||||
// If not a superset, create an AbstractFuncUnion with both AbstractFunctions.
|
||||
return std::make_shared<AbstractFuncUnion>(this_func, other);
|
||||
}
|
||||
|
||||
// Visit function to perform an operation on each element of the AbstractFuncUnion.
|
||||
void AbstractFuncUnion::Visit(std::function<void(const AbstractFuncAtomPtr &)> visit_func) const {
|
||||
for (const AbstractFuncAtomPtr &poss : func_list_) {
|
||||
visit_func(poss);
|
||||
}
|
||||
}
|
||||
|
||||
// Equality comparison operator for AbstractFunction.
|
||||
bool AbstractFuncUnion::operator==(const AbstractFunction &other) const {
|
||||
if (!other.isa<AbstractFuncUnion>()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto other_union = static_cast<const AbstractFuncUnion *>(&other);
|
||||
|
||||
if (func_list_.size() != other_union->func_list_.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the func_list_ vectors are equal.
|
||||
return func_list_ == other_union->func_list_;
|
||||
}
|
||||
|
||||
// Hash function for AbstractFuncUnion.
|
||||
std::size_t AbstractFuncUnion::hash() const {
|
||||
std::size_t hash_sum = 0;
|
||||
|
||||
for (const auto &f : func_list_) {
|
||||
MS_EXCEPTION_IF_NULL(f);
|
||||
hash_sum = hash_combine(hash_sum, f->hash());
|
||||
}
|
||||
|
||||
return hash_sum;
|
||||
}
|
||||
|
||||
// Equality comparison operator for PrimitiveAbstractClosure.
|
||||
bool PrimitiveAbstractClosure::operator==(const AbstractFunction &other) const {
|
||||
if (!other.isa<PrimitiveAbstractClosure>()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto &other_abs = static_cast<const PrimitiveAbstractClosure &>(other);
|
||||
// Check if both 'prim_' and 'tracking_id()' are equal.
|
||||
return (prim_ == other_abs.prim_) && (tracking_id() == other_abs.tracking_id());
|
||||
}
|
||||
|
||||
// Hash function for PrimitiveAbstractClosure.
|
||||
std::size_t PrimitiveAbstractClosure::hash() const {
|
||||
// Keep in sync with operator==() which compares tid, prim_ & tracking_id;
|
||||
auto hash_value = static_cast<std::size_t>(tid());
|
||||
|
|
@ -170,6 +243,7 @@ std::size_t PrimitiveAbstractClosure::hash() const {
|
|||
return hash_value;
|
||||
}
|
||||
|
||||
// Convert PrimitiveAbstractClosure to a string.
|
||||
std::string PrimitiveAbstractClosure::ToString(bool verbose) const {
|
||||
if (verbose) {
|
||||
return ToString();
|
||||
|
|
@ -177,15 +251,18 @@ std::string PrimitiveAbstractClosure::ToString(bool verbose) const {
|
|||
return type_name() + " (" + prim_->name() + ")";
|
||||
}
|
||||
|
||||
// Equality comparison operator for FuncGraphAbstractClosure.
|
||||
bool FuncGraphAbstractClosure::operator==(const AbstractFunction &other) const {
|
||||
if (!other.isa<FuncGraphAbstractClosure>()) {
|
||||
return false;
|
||||
}
|
||||
auto other_fg = static_cast<const FuncGraphAbstractClosure *>(&other);
|
||||
// Check if 'func_graph_', 'context_', and 'tracking_id()' are equal.
|
||||
return func_graph_ == other_fg->func_graph_ && context_ == other_fg->context_ &&
|
||||
tracking_id() == other_fg->tracking_id();
|
||||
}
|
||||
|
||||
// Hash function for FuncGraphAbstractClosure.
|
||||
std::size_t FuncGraphAbstractClosure::hash() const {
|
||||
auto hash_value = hash_combine(tid(), func_graph_->hash());
|
||||
hash_value = hash_combine(hash_value, context_->hash());
|
||||
|
|
@ -195,6 +272,7 @@ std::size_t FuncGraphAbstractClosure::hash() const {
|
|||
return hash_value;
|
||||
}
|
||||
|
||||
// Convert FuncGraphAbstractClosure to a string.
|
||||
std::string FuncGraphAbstractClosure::ToString() const {
|
||||
std::stringstream ss;
|
||||
MS_EXCEPTION_IF_NULL(func_graph_);
|
||||
|
|
@ -204,6 +282,7 @@ std::string FuncGraphAbstractClosure::ToString() const {
|
|||
return ss.str();
|
||||
}
|
||||
|
||||
// Convert FuncGraphAbstractClosure to a string, optionally in a verbose mode.
|
||||
std::string FuncGraphAbstractClosure::ToString(bool verbose) const {
|
||||
if (verbose) {
|
||||
return ToString();
|
||||
|
|
@ -214,14 +293,17 @@ std::string FuncGraphAbstractClosure::ToString(bool verbose) const {
|
|||
return ss.str();
|
||||
}
|
||||
|
||||
// Equality comparison operator for MetaFuncGraphAbstractClosure.
|
||||
bool MetaFuncGraphAbstractClosure::operator==(const AbstractFunction &other) const {
|
||||
if (!other.isa<MetaFuncGraphAbstractClosure>()) {
|
||||
return false;
|
||||
}
|
||||
auto other_meta_fg = static_cast<const MetaFuncGraphAbstractClosure *>(&other);
|
||||
// Check if 'meta_func_graph_' and 'tracking_id()' are equal.
|
||||
return meta_func_graph_ == other_meta_fg->meta_func_graph_ && tracking_id() == other_meta_fg->tracking_id();
|
||||
}
|
||||
|
||||
// Hash function for MetaFuncGraphAbstractClosure.
|
||||
std::size_t MetaFuncGraphAbstractClosure::hash() const {
|
||||
MS_EXCEPTION_IF_NULL(meta_func_graph_);
|
||||
auto hash_value = hash_combine(tid(), meta_func_graph_->hash());
|
||||
|
|
@ -231,16 +313,19 @@ std::size_t MetaFuncGraphAbstractClosure::hash() const {
|
|||
return hash_value;
|
||||
}
|
||||
|
||||
// Convert MetaFuncGraphAbstractClosure to a string.
|
||||
std::string MetaFuncGraphAbstractClosure::ToString() const {
|
||||
MS_EXCEPTION_IF_NULL(meta_func_graph_);
|
||||
return "MetaFuncGraphAbstractClosure: " + meta_func_graph_->name();
|
||||
}
|
||||
|
||||
// Equality comparison operator for PartialAbstractClosure.
|
||||
bool PartialAbstractClosure::operator==(const AbstractFunction &other) const {
|
||||
if (!other.isa<PartialAbstractClosure>()) {
|
||||
return false;
|
||||
}
|
||||
auto other_partial = static_cast<const PartialAbstractClosure *>(&other);
|
||||
// Check if 'fn_' and 'args_spec_list_' are equal.
|
||||
if (fn_ != other_partial->fn_) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -250,6 +335,7 @@ bool PartialAbstractClosure::operator==(const AbstractFunction &other) const {
|
|||
return args_spec_list_ == other_partial->args_spec_list_;
|
||||
}
|
||||
|
||||
// Hash function for PartialAbstractClosure.
|
||||
std::size_t PartialAbstractClosure::hash() const {
|
||||
MS_EXCEPTION_IF_NULL(fn_);
|
||||
auto hash_value = hash_combine(tid(), fn_->hash());
|
||||
|
|
@ -257,6 +343,7 @@ std::size_t PartialAbstractClosure::hash() const {
|
|||
return hash_value;
|
||||
}
|
||||
|
||||
// Convert PartialAbstractClosure to a string.
|
||||
std::string PartialAbstractClosure::ToString() const {
|
||||
std::ostringstream buffer;
|
||||
buffer << "PartialAbstractClosure(" << fn_->ToString() << "(";
|
||||
|
|
@ -274,6 +361,7 @@ std::string PartialAbstractClosure::ToString() const {
|
|||
return buffer.str();
|
||||
}
|
||||
|
||||
// Convert PartialAbstractClosure to a string, optionally in a verbose mode.
|
||||
std::string PartialAbstractClosure::ToString(bool verbose) const {
|
||||
if (verbose) {
|
||||
return ToString();
|
||||
|
|
@ -283,57 +371,69 @@ std::string PartialAbstractClosure::ToString(bool verbose) const {
|
|||
return buffer.str();
|
||||
}
|
||||
|
||||
// Equality comparison operator for JTransformedAbstractClosure.
|
||||
bool JTransformedAbstractClosure::operator==(const AbstractFunction &other) const {
|
||||
if (!other.isa<JTransformedAbstractClosure>()) {
|
||||
return false;
|
||||
}
|
||||
auto other_transformed = static_cast<const JTransformedAbstractClosure *>(&other);
|
||||
// Check if 'fn_' is equal.
|
||||
return fn_ == other_transformed->fn_;
|
||||
}
|
||||
|
||||
// Hash function for JTransformedAbstractClosure.
|
||||
std::size_t JTransformedAbstractClosure::hash() const {
|
||||
MS_EXCEPTION_IF_NULL(fn_);
|
||||
auto hash_value = hash_combine(tid(), fn_->hash());
|
||||
return hash_value;
|
||||
}
|
||||
|
||||
// Equality comparison operator for TaylorTransformedAbstractClosure.
|
||||
bool TaylorTransformedAbstractClosure::operator==(const AbstractFunction &other) const {
|
||||
if (!other.isa<TaylorTransformedAbstractClosure>()) {
|
||||
return false;
|
||||
}
|
||||
auto other_transformed = static_cast<const TaylorTransformedAbstractClosure *>(&other);
|
||||
// Check if 'fn_' is equal.
|
||||
return fn_ == other_transformed->fn_;
|
||||
}
|
||||
|
||||
// Hash function for TaylorTransformedAbstractClosure.
|
||||
std::size_t TaylorTransformedAbstractClosure::hash() const {
|
||||
MS_EXCEPTION_IF_NULL(fn_);
|
||||
auto hash_value = hash_combine(tid(), fn_->hash());
|
||||
return hash_value;
|
||||
}
|
||||
|
||||
// Equality comparison operator for ShardTransformedAbstractClosure.
|
||||
bool ShardTransformedAbstractClosure::operator==(const AbstractFunction &other) const {
|
||||
if (!other.isa<ShardTransformedAbstractClosure>()) {
|
||||
return false;
|
||||
}
|
||||
auto other_transformed = static_cast<const ShardTransformedAbstractClosure *>(&other);
|
||||
// Check if 'fn_' is equal.
|
||||
return fn_ == other_transformed->fn_;
|
||||
}
|
||||
|
||||
// Hash function for ShardTransformedAbstractClosure.
|
||||
std::size_t ShardTransformedAbstractClosure::hash() const {
|
||||
MS_EXCEPTION_IF_NULL(fn_);
|
||||
auto hash_value = hash_combine(tid(), fn_->hash());
|
||||
return hash_value;
|
||||
}
|
||||
|
||||
// Equality comparison operator for VmapTransformedAbstractClosure.
|
||||
bool VmapTransformedAbstractClosure::operator==(const AbstractFunction &other) const {
|
||||
if (!other.isa<VmapTransformedAbstractClosure>()) {
|
||||
return false;
|
||||
}
|
||||
auto other_transformed = static_cast<const VmapTransformedAbstractClosure *>(&other);
|
||||
// Check if 'fn_', 'in_axes_', and 'out_axes_' are equal.
|
||||
return fn_ == other_transformed->fn_ && in_axes_ == other_transformed->in_axes_ &&
|
||||
out_axes_ == other_transformed->out_axes_;
|
||||
}
|
||||
|
||||
// Hash function for VmapTransformedAbstractClosure.
|
||||
std::size_t VmapTransformedAbstractClosure::hash() const {
|
||||
MS_EXCEPTION_IF_NULL(fn_);
|
||||
MS_EXCEPTION_IF_NULL(in_axes_);
|
||||
|
|
@ -342,11 +442,13 @@ std::size_t VmapTransformedAbstractClosure::hash() const {
|
|||
return hash_value;
|
||||
}
|
||||
|
||||
// Equality comparison operator for VirtualAbstractClosure.
|
||||
bool VirtualAbstractClosure::operator==(const AbstractFunction &other) const {
|
||||
if (!other.isa<VirtualAbstractClosure>()) {
|
||||
return false;
|
||||
}
|
||||
auto other_virtual = static_cast<const VirtualAbstractClosure *>(&other);
|
||||
// Check if 'output_' and 'args_spec_list_' are equal.
|
||||
if (output_ != other_virtual->output_) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -356,6 +458,7 @@ bool VirtualAbstractClosure::operator==(const AbstractFunction &other) const {
|
|||
return args_spec_list_ == other_virtual->args_spec_list_;
|
||||
}
|
||||
|
||||
// Hash function for VirtualAbstractClosure.
|
||||
std::size_t VirtualAbstractClosure::hash() const {
|
||||
MS_EXCEPTION_IF_NULL(output_);
|
||||
auto hash_value = hash_combine(tid(), output_->hash());
|
||||
|
|
@ -363,6 +466,7 @@ std::size_t VirtualAbstractClosure::hash() const {
|
|||
return hash_value;
|
||||
}
|
||||
|
||||
// Convert VirtualAbstractClosure to a string.
|
||||
std::string VirtualAbstractClosure::ToString() const {
|
||||
std::ostringstream buffer;
|
||||
buffer << "VirtualAbstractClosure(args: {";
|
||||
|
|
@ -383,11 +487,13 @@ std::string VirtualAbstractClosure::ToString() const {
|
|||
return buffer.str();
|
||||
}
|
||||
|
||||
// Equality comparison operator for TypedPrimitiveAbstractClosure.
|
||||
bool TypedPrimitiveAbstractClosure::operator==(const AbstractFunction &other) const {
|
||||
if (!other.isa<TypedPrimitiveAbstractClosure>()) {
|
||||
return false;
|
||||
}
|
||||
auto other_typed = static_cast<const TypedPrimitiveAbstractClosure *>(&other);
|
||||
// Check if 'output_', 'prim_', and 'args_spec_list_' are equal.
|
||||
if (output_ != other_typed->output_) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -400,15 +506,20 @@ bool TypedPrimitiveAbstractClosure::operator==(const AbstractFunction &other) co
|
|||
return args_spec_list_ == other_typed->args_spec_list_;
|
||||
}
|
||||
|
||||
// Hash function for TypedPrimitiveAbstractClosure.
|
||||
std::size_t TypedPrimitiveAbstractClosure::hash() const {
|
||||
auto hash_value = hash_combine(tid(), prim_->hash());
|
||||
MS_EXCEPTION_IF_NULL(output_);
|
||||
MS_EXCEPTION_IF_NULL(prim_);
|
||||
auto hash_value = hash_combine(tid(), output_->hash());
|
||||
hash_value = hash_combine(hash_value, PointerHash<PrimitivePtr>{}(prim_));
|
||||
hash_value = hash_combine(hash_value, AbstractBasePtrListHash(args_spec_list_));
|
||||
return hash_value;
|
||||
}
|
||||
|
||||
// Convert TypedPrimitiveAbstractClosure to a string.
|
||||
std::string TypedPrimitiveAbstractClosure::ToString() const {
|
||||
std::ostringstream buffer;
|
||||
buffer << "TypedPrimitiveAbstractClosure: primitive: " << prim_->name() << "(args: {";
|
||||
buffer << "TypedPrimitiveAbstractClosure(args: {";
|
||||
int64_t i = 0;
|
||||
for (const auto &arg : args_spec_list_) {
|
||||
MS_EXCEPTION_IF_NULL(arg);
|
||||
|
|
@ -425,5 +536,6 @@ std::string TypedPrimitiveAbstractClosure::ToString() const {
|
|||
buffer << "}, output: " << output_->ToString() << ")";
|
||||
return buffer.str();
|
||||
}
|
||||
|
||||
} // namespace abstract
|
||||
} // namespace mindspore
|
||||
|
|
|
|||
|
|
@ -38,14 +38,25 @@ class MS_CORE_API AbstractFuncAtom : public AbstractFunction {
|
|||
~AbstractFuncAtom() override = default;
|
||||
MS_DECLARE_PARENT(AbstractFuncAtom, AbstractFunction)
|
||||
|
||||
/// Override the GetUnique function to return a shared pointer to the current instance.
|
||||
AbstractFunctionPtr GetUnique() override { return shared_from_base<AbstractFuncAtom>(); }
|
||||
|
||||
/// Override the Join function to merge two instances of AbstractFunction.
|
||||
/// \param[in] other: Another instance of AbstractFunction to merge with.
|
||||
/// \return The merged AbstractFunction.
|
||||
AbstractFunctionPtr Join(const AbstractFunctionPtr &other) final;
|
||||
|
||||
/// Override the Visit function to perform an action on the current instance.
|
||||
/// \param[in] func: A function that accepts an AbstractFuncAtomPtr and performs an action on it.
|
||||
void Visit(std::function<void(const AbstractFuncAtomPtr &)>) const final;
|
||||
|
||||
/// Override the equality operator to compare the current instance with another AbstractFunction.
|
||||
/// \param[in] other: Another AbstractFunction to compare with.
|
||||
/// \return True if the two instances are equal, false otherwise.
|
||||
bool operator==(const AbstractFunction &other) const override;
|
||||
|
||||
/// Override the hash function to return the type ID as a hash value.
|
||||
/// \return The hash value based on the type ID.
|
||||
std::size_t hash() const override { return tid(); }
|
||||
};
|
||||
|
||||
|
|
@ -80,14 +91,26 @@ class MS_CORE_API AbstractFuncUnion final : public AbstractFunction {
|
|||
/// \return Return true if other is in AbstractFuncUnion, otherwise return False.
|
||||
bool IsSuperSet(const AbstractFunctionPtr &other);
|
||||
|
||||
/// Override the Join function to merge two instances of AbstractFunction.
|
||||
/// \param[in] other: Another instance of AbstractFunction to merge with.
|
||||
/// \return The merged AbstractFunction.
|
||||
AbstractFunctionPtr Join(const AbstractFunctionPtr &other) final;
|
||||
|
||||
/// Override the Visit function to perform an action on the current instance.
|
||||
/// \param[in] func: A function that accepts an AbstractFuncAtomPtr and performs an action on it.
|
||||
void Visit(std::function<void(const AbstractFuncAtomPtr &)>) const final;
|
||||
|
||||
/// Override the equality operator to compare the current instance with another AbstractFunction.
|
||||
/// \param[in] other: Another AbstractFunction to compare with.
|
||||
/// \return True if the two instances are equal, false otherwise.
|
||||
bool operator==(const AbstractFunction &other) const override;
|
||||
|
||||
/// Override the hash function to return the type ID as a hash value.
|
||||
/// \return The hash value based on the type ID.
|
||||
std::size_t hash() const override;
|
||||
|
||||
/// Override the Copy function to create a copy of the current instance.
|
||||
/// This function should not be used for AbstractFuncUnion, so it throws an exception.
|
||||
AbstractFunctionPtr Copy() const override { MS_LOG(EXCEPTION) << "Cannot Copy from AbstractFuncUnion"; }
|
||||
|
||||
private:
|
||||
|
|
@ -113,20 +136,38 @@ class MS_CORE_API PrimitiveAbstractClosure final : public AbstractFuncAtom {
|
|||
/// \return The Primitive that this PrimitiveAbstractClosure corresponding to.
|
||||
PrimitivePtr prim() { return prim_; }
|
||||
|
||||
/// Override the tracking_id function to get the tracking ID of this AbstractFunction.
|
||||
/// \return The tracking ID of this AbstractFunction as an AnfNodePtr.
|
||||
AnfNodePtr tracking_id() const override { return tracking_id_.lock(); }
|
||||
|
||||
/// Override the set_tracking_id function to set the tracking ID of this AbstractFunction.
|
||||
/// \param[in] node: The AnfNodePtr to set as the tracking ID.
|
||||
void set_tracking_id(AnfNodePtr node) override { tracking_id_ = AnfNodeWeakPtr(node); }
|
||||
|
||||
/// Override the Copy function to create a copy of the current instance.
|
||||
/// \return A copy of the current AbstractFunction as an AbstractFunctionPtr.
|
||||
AbstractFunctionPtr Copy() const override { return std::make_shared<PrimitiveAbstractClosure>(prim_, tracking_id()); }
|
||||
|
||||
/// Override the equality operator to compare the current instance with another AbstractFunction.
|
||||
/// \param[in] other: Another AbstractFunction to compare with.
|
||||
/// \return True if the two instances are equal, false otherwise.
|
||||
bool operator==(const AbstractFunction &other) const override;
|
||||
|
||||
/// Override the hash function to return a hash value based on the type ID.
|
||||
/// \return The hash value based on the type ID.
|
||||
std::size_t hash() const override;
|
||||
|
||||
/// Override the ToString function to provide a string representation of this AbstractFunction.
|
||||
/// \return A string describing this AbstractFunction.
|
||||
std::string ToString() const override { return "Prim: " + prim_->name(); }
|
||||
|
||||
/// Override the ToString function to provide a string representation of this AbstractFunction with verbosity.
|
||||
/// \param[in] verbose: A flag indicating whether to include verbose information.
|
||||
/// \return A string describing this AbstractFunction with optional verbosity.
|
||||
std::string ToString(bool verbose) const override;
|
||||
|
||||
/// Override the RealBuildValue function to return the associated primitive as a ValuePtr.
|
||||
/// \return The primitive associated with this AbstractFunction as a ValuePtr.
|
||||
ValuePtr RealBuildValue() const override { return prim_; }
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -24,7 +24,13 @@
|
|||
|
||||
namespace mindspore {
|
||||
namespace abstract {
|
||||
/// \brief A static list that stores all AnalysisContext instances.
|
||||
std::list<AnalysisContextPtr> AnalysisContext::all_context_;
|
||||
|
||||
/// \brief Creates a new AnalysisContext for a given FuncGraph and argument specifications.
|
||||
/// \param func_graph The FuncGraph for which the AnalysisContext is created.
|
||||
/// \param args_spec_list The list of AbstractBasePtr representing argument specifications.
|
||||
/// \return A shared pointer to the newly created AnalysisContext.
|
||||
AnalysisContextPtr AnalysisContext::NewContext(const FuncGraphPtr &func_graph,
|
||||
const AbstractBasePtrList &args_spec_list) {
|
||||
// Find func graph's parent and its parent context firstly.
|
||||
|
|
@ -32,10 +38,14 @@ AnalysisContextPtr AnalysisContext::NewContext(const FuncGraphPtr &func_graph,
|
|||
FuncGraphPtr parent_graph = func_graph->parent();
|
||||
AnalysisContextPtr parent_context = nullptr;
|
||||
auto iter = extant_context_cache_.find(parent_graph);
|
||||
|
||||
// If the parent context exists in the cache, get a shared pointer to it.
|
||||
if (iter != extant_context_cache_.end()) {
|
||||
parent_context = iter->second.lock();
|
||||
}
|
||||
if (parent_context == nullptr) { // If parent context is not found, we'll raise exception.
|
||||
|
||||
// If the parent context is not found, raise an exception with detailed information.
|
||||
if (parent_context == nullptr) {
|
||||
std::ostringstream oss;
|
||||
oss << "BUG: Failed to find parent context in current context: " << this->ToString()
|
||||
<< ", func_graph: " << func_graph->ToString() << ", parent_graph: ";
|
||||
|
|
@ -52,6 +62,8 @@ AnalysisContextPtr AnalysisContext::NewContext(const FuncGraphPtr &func_graph,
|
|||
if (children_context_map_iter != parent_context->children_cache_.end()) {
|
||||
auto children_context_map = children_context_map_iter->second;
|
||||
auto children_context_iter = children_context_map.find(args_spec_list);
|
||||
|
||||
// If a context with the same arguments exists in the cache, return a shared pointer to it.
|
||||
if (children_context_iter != children_context_map.end()) {
|
||||
return children_context_iter->second.lock();
|
||||
}
|
||||
|
|
@ -59,25 +71,36 @@ AnalysisContextPtr AnalysisContext::NewContext(const FuncGraphPtr &func_graph,
|
|||
|
||||
// Create a new context for the func graph and its specific arguments.
|
||||
AnalysisContextPtr new_context = CreateContext(parent_context, func_graph, args_spec_list);
|
||||
|
||||
// To avoid cycle-reference, use weak_ptr here.
|
||||
auto weak_new_context = std::weak_ptr<AnalysisContext>(new_context);
|
||||
new_context->extant_context_cache_[func_graph] = weak_new_context;
|
||||
parent_context->children_cache_[func_graph][args_spec_list] = weak_new_context;
|
||||
|
||||
return new_context;
|
||||
}
|
||||
|
||||
/// \brief Finds the AnalysisContext for a given FuncGraph or its parent FuncGraph.
|
||||
/// \param func_graph The FuncGraph for which the AnalysisContext is searched.
|
||||
/// \return A shared pointer to the found AnalysisContext.
|
||||
AnalysisContextPtr AnalysisContext::FindOwnOrParentContext(const FuncGraphPtr &func_graph) {
|
||||
auto p_iter = extant_context_cache_.find(func_graph);
|
||||
AnalysisContextPtr extant_context = nullptr;
|
||||
|
||||
// If the context for the given FuncGraph is found in the cache, get a shared pointer to it.
|
||||
if (p_iter != extant_context_cache_.end()) {
|
||||
extant_context = p_iter->second.lock();
|
||||
} else {
|
||||
// If not found, try to find the context for its parent FuncGraph.
|
||||
auto iter_parent = extant_context_cache_.find(func_graph->parent());
|
||||
|
||||
// If found, get a shared pointer to the parent context.
|
||||
if (iter_parent != extant_context_cache_.end()) {
|
||||
extant_context = iter_parent->second.lock();
|
||||
}
|
||||
}
|
||||
// If this happen, it would be a bug in code. But we raise exception to keep the scene.
|
||||
|
||||
// If the context is still not found, raise an exception with detailed information.
|
||||
if (extant_context == nullptr) {
|
||||
std::ostringstream oss;
|
||||
oss << "BUG: Failed to find context for: " << func_graph->ToString() << ", parent_graph: ";
|
||||
|
|
@ -93,42 +116,55 @@ AnalysisContextPtr AnalysisContext::FindOwnOrParentContext(const FuncGraphPtr &f
|
|||
} else {
|
||||
oss << " [graph: " << iter.first->ToString();
|
||||
}
|
||||
// iter.second cannot be nullptr even iter.first is nullptr as it will
|
||||
// iter.second cannot be nullptr even if iter.first is nullptr, as it will
|
||||
// always be a Context() object.
|
||||
oss << ", context: " << iter.second.lock()->ToString() << "]";
|
||||
}
|
||||
oss << "}";
|
||||
MS_LOG(EXCEPTION) << oss.str() << " NodeInfo: " << trace::GetDebugInfo(func_graph->debug_info());
|
||||
}
|
||||
|
||||
return extant_context;
|
||||
}
|
||||
|
||||
/// \brief Creates a dummy AnalysisContext that represents no specific function or arguments.
|
||||
/// \return A shared pointer to the created dummy AnalysisContext.
|
||||
AnalysisContextPtr AnalysisContext::DummyContext() {
|
||||
AnalysisContextPtr dummy_context = CreateContext(nullptr, nullptr, AbstractBasePtrList());
|
||||
dummy_context->extant_context_cache_[nullptr] = std::weak_ptr<AnalysisContext>(dummy_context);
|
||||
return dummy_context;
|
||||
}
|
||||
|
||||
/// \brief Checks if the AnalysisContext is a dummy context with no specific function or arguments.
|
||||
/// \return True if it's a dummy context, false otherwise.
|
||||
bool AnalysisContext::IsDummyContext() {
|
||||
return parent_ == nullptr && func_graph_ == nullptr && args_spec_list_.empty();
|
||||
}
|
||||
|
||||
/// \brief An instance of AnalysisContext that represents a dummy context.
|
||||
const AnalysisContextPtr kDummyAnalysisContext =
|
||||
AnalysisContext::CreateContext(nullptr, nullptr, AbstractBasePtrList());
|
||||
|
||||
/// \brief Checks if two AnalysisContext instances are equal.
|
||||
/// \param other The other AnalysisContext instance to compare with.
|
||||
/// \return True if they are equal, false otherwise.
|
||||
bool AnalysisContext::operator==(const AnalysisContext &other) const {
|
||||
// Check if func_graph_ is equal.
|
||||
if (func_graph_ != other.func_graph_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if args_spec_list_ size is equal.
|
||||
if (args_spec_list_.size() != other.args_spec_list_.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if parent_ is either both nullptr or both not nullptr.
|
||||
if (((parent_ == nullptr) && (other.parent_ != nullptr)) || ((parent_ != nullptr) && (other.parent_ == nullptr))) {
|
||||
return false;
|
||||
}
|
||||
// Compare parent with content.
|
||||
|
||||
// Compare parent_ with content.
|
||||
bool is_parent_equal = false;
|
||||
if (parent_ == other.parent_) {
|
||||
is_parent_equal = true;
|
||||
|
|
@ -137,33 +173,43 @@ bool AnalysisContext::operator==(const AnalysisContext &other) const {
|
|||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Compare each element in args_spec_list_.
|
||||
for (std::size_t i = 0; i < args_spec_list_.size(); i++) {
|
||||
if (func_graph_->has_flag(GRAPH_FLAG_IS_WHILE_HEADER) &&
|
||||
args_spec_list_[i]->isa<abstract::FuncGraphAbstractClosure>() &&
|
||||
other.args_spec_list_[i]->isa<abstract::FuncGraphAbstractClosure>()) {
|
||||
// If both are FuncGraphAbstractClosure, make a copy and compare without tracking IDs.
|
||||
auto temp_this = args_spec_list_[i]->cast<abstract::FuncGraphAbstractClosurePtr>()->Copy();
|
||||
auto temp_other = other.args_spec_list_[i]->cast<abstract::FuncGraphAbstractClosurePtr>()->Copy();
|
||||
temp_this->set_tracking_id(nullptr);
|
||||
temp_other->set_tracking_id(nullptr);
|
||||
|
||||
// If the copies are not equal, return false.
|
||||
if (!(*temp_this == *temp_other)) {
|
||||
return false;
|
||||
}
|
||||
} else if (!(*args_spec_list_[i] == *other.args_spec_list_[i])) {
|
||||
// If not both FuncGraphAbstractClosure, compare directly.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return is_parent_equal;
|
||||
}
|
||||
|
||||
// brief The key which controls the graph cloning in Specialize.
|
||||
// Originally, specialize use context directly as the key for cloning graph. The graph will be cloned multiple times
|
||||
// for different context, which means the graph is called from different node with different arguments and different
|
||||
// free values. In order to decrease the number of cloned graphs, we add this `SpecializeKey` method to control what
|
||||
// graph can be reused.
|
||||
// The graph called with different shape should not be reused, because the combination of `shape` and `Fill` relies
|
||||
// on correct shape to specialize a tensor constant.
|
||||
/// \brief Generates a key for controlling graph cloning during specialization.
|
||||
/// Originally, specialization used the context directly as the key for cloning graphs. This led to multiple clones of
|
||||
/// the same graph for different contexts, where the graph was called from different nodes with varying arguments and
|
||||
/// free values. To reduce the number of cloned graphs, this method, `SpecializeKey`, is introduced to determine which
|
||||
/// graphs can be reused.
|
||||
/// Graphs called with different shapes should not be reused because the specialization of a tensor constant depends on
|
||||
/// the correct shape.
|
||||
/// \return A new AnalysisContextPtr representing the specialized key.
|
||||
AnalysisContextPtr AnalysisContext::SpecializeKey() const {
|
||||
// Create a list for broadened arguments.
|
||||
AbstractBasePtrList args_broad_shp;
|
||||
|
||||
// Iterate through the args_spec_list_ and add the broadened version of each argument to args_broad_shp.
|
||||
(void)std::transform(args_spec_list_.begin(), args_spec_list_.end(), std::back_inserter(args_broad_shp),
|
||||
[](const AbstractBasePtr &arg) -> AbstractBasePtr {
|
||||
MS_EXCEPTION_IF_NULL(arg);
|
||||
|
|
@ -173,23 +219,34 @@ AnalysisContextPtr AnalysisContext::SpecializeKey() const {
|
|||
}
|
||||
return arg;
|
||||
});
|
||||
|
||||
// Create a new AnalysisContext using the broadened arguments and the same function graph.
|
||||
AnalysisContextPtr context_new = CreateContext(nullptr, func_graph_, args_broad_shp);
|
||||
context_new->parent_ = parent_;
|
||||
|
||||
return context_new;
|
||||
}
|
||||
|
||||
/// \brief Computes a hash value for the AnalysisContext instance.
|
||||
/// The hash value is used for hashing and comparison purposes.
|
||||
/// \return The computed hash value.
|
||||
std::size_t AnalysisContext::hash() {
|
||||
std::size_t hash_value = 0;
|
||||
// hash() recursion exit condition.
|
||||
|
||||
// Recursion exit condition for hash().
|
||||
if (parent_ != nullptr) {
|
||||
hash_value = hash_combine(hash_value, parent_->hash());
|
||||
}
|
||||
if (func_graph_ != nullptr) {
|
||||
hash_value = hash_combine(hash_value, func_graph_->hash());
|
||||
}
|
||||
|
||||
return hash_value;
|
||||
}
|
||||
|
||||
/// \brief Converts the AnalysisContext instance to a string representation.
|
||||
/// This method is primarily used for debugging and logging purposes.
|
||||
/// \return A string representing the AnalysisContext.
|
||||
std::string AnalysisContext::ToString() const {
|
||||
std::ostringstream buffer;
|
||||
buffer << "{";
|
||||
|
|
@ -209,6 +266,7 @@ std::string AnalysisContext::ToString() const {
|
|||
return buffer.str();
|
||||
}
|
||||
|
||||
/// \brief Clears all contexts stored in the `all_context_` list.
|
||||
void AnalysisContext::ClearContext() {
|
||||
for (auto &item : all_context_) {
|
||||
item->parent_ = nullptr;
|
||||
|
|
@ -220,6 +278,11 @@ void AnalysisContext::ClearContext() {
|
|||
all_context_.clear();
|
||||
}
|
||||
|
||||
/// \brief Creates a new AnalysisContext instance.
|
||||
/// \param parent The parent context.
|
||||
/// \param fg The FuncGraph associated with the context.
|
||||
/// \param args_spec_list The list of AbstractBasePtr representing argument specifications.
|
||||
/// \return A shared pointer to the newly created AnalysisContext.
|
||||
AnalysisContextPtr AnalysisContext::CreateContext(const AnalysisContextPtr &parent, const FuncGraphPtr &fg,
|
||||
const AbstractBasePtrList &args_spec_list) {
|
||||
auto context = std::make_shared<AnalysisContext>(parent, fg, args_spec_list);
|
||||
|
|
|
|||
|
|
@ -47,38 +47,86 @@ class MS_CORE_API AnalysisContext {
|
|||
}
|
||||
~AnalysisContext() = default;
|
||||
|
||||
// Extend this context with values for another graph.
|
||||
/// Create a new AnalysisContext for a given function graph and its associated argument specifications.
|
||||
/// \param[in] func_graph: The FuncGraphPtr representing the function graph for which to create the context.
|
||||
/// \param[in] args_spec_list: The AbstractBasePtrList containing argument specifications.
|
||||
/// \return A new AnalysisContextPtr representing the context for the given function graph and arguments.
|
||||
AnalysisContextPtr NewContext(const FuncGraphPtr &func_graph, const AbstractBasePtrList &args_spec_list);
|
||||
|
||||
// Return a context restricted to a graph and its parent.
|
||||
/// Find the AnalysisContext for a given function graph, or its parent if not found.
|
||||
/// \param[in] graph: The FuncGraphPtr for which to find the context.
|
||||
/// \return The AnalysisContextPtr for the specified function graph or its parent.
|
||||
AnalysisContextPtr FindOwnOrParentContext(const FuncGraphPtr &graph);
|
||||
|
||||
/// Override the equality operator to compare two AnalysisContext instances.
|
||||
/// \param[in] other: Another AnalysisContext to compare with.
|
||||
/// \return True if the two AnalysisContext instances are equal, false otherwise.
|
||||
bool operator==(const AnalysisContext &other) const;
|
||||
|
||||
/// Calculate a hash value for the AnalysisContext instance.
|
||||
/// \return The hash value for the AnalysisContext.
|
||||
std::size_t hash();
|
||||
|
||||
/// Create a dummy AnalysisContextPtr, typically used as a placeholder.
|
||||
/// \return A dummy AnalysisContextPtr.
|
||||
static AnalysisContextPtr DummyContext();
|
||||
|
||||
/// Check if the current AnalysisContext is a dummy context.
|
||||
/// \return True if the current context is a dummy context, false otherwise.
|
||||
bool IsDummyContext();
|
||||
|
||||
/// Get the function graph associated with this AnalysisContext.
|
||||
/// \return The FuncGraphPtr associated with this context.
|
||||
FuncGraphPtr func_graph() const { return func_graph_; }
|
||||
|
||||
/// Get the parent context of this AnalysisContext.
|
||||
/// \return The parent AnalysisContextPtr of this context.
|
||||
AnalysisContextPtr parent() const { return parent_; }
|
||||
|
||||
/// Convert the AnalysisContext to a string representation.
|
||||
/// \return A string representation of the AnalysisContext.
|
||||
std::string ToString() const;
|
||||
|
||||
/// Specialize the current context key.
|
||||
/// \return A specialized AnalysisContextPtr based on the current context key.
|
||||
AnalysisContextPtr SpecializeKey() const;
|
||||
|
||||
/// Get the list of argument specifications associated with this context.
|
||||
/// \return The AbstractBasePtrList containing argument specifications.
|
||||
AbstractBasePtrList args_spec_list() { return args_spec_list_; }
|
||||
|
||||
/// Clear the current context, typically used for resetting context information.
|
||||
static void ClearContext();
|
||||
|
||||
/// Create a new AnalysisContext with the given parent, function graph, and argument specifications.
|
||||
/// \param[in] parent: The parent AnalysisContextPtr.
|
||||
/// \param[in] fg: The FuncGraphPtr representing the function graph.
|
||||
/// \param[in] args_spec_list: The AbstractBasePtrList containing argument specifications.
|
||||
/// \return A new AnalysisContextPtr created with the specified parameters.
|
||||
static AnalysisContextPtr CreateContext(const AnalysisContextPtr &parent, const FuncGraphPtr &fg,
|
||||
const AbstractBasePtrList &args_spec_list);
|
||||
|
||||
private:
|
||||
// Pointer to the parent AnalysisContext.
|
||||
AnalysisContextPtr parent_;
|
||||
|
||||
// Pointer to the associated function graph.
|
||||
FuncGraphPtr func_graph_;
|
||||
|
||||
// List of argument specifications associated with this context.
|
||||
AbstractBasePtrList args_spec_list_;
|
||||
// Record all created context for each func graph.
|
||||
// `extant_context_cache_` is copied from its parent context.
|
||||
|
||||
// A HashMap that records all created context instances for each function graph.
|
||||
// The extant_context_cache_ is copied from its parent context.
|
||||
mindspore::HashMap<FuncGraphPtr, AnalysisContextWeakPtr> extant_context_cache_;
|
||||
// Record all created child contexts from this context.
|
||||
// Like: key: [func_graph & arguments], value: [child_context]
|
||||
|
||||
// A HashMap that records all created child contexts from this context.
|
||||
// The key is a combination of [function graph & arguments], and the value is the child context.
|
||||
mindspore::HashMap<FuncGraphPtr, ArgsSpecToAnalysisContextMap> children_cache_;
|
||||
|
||||
// There may may be shared_ptr loop like:
|
||||
// FuncGraphAbstactClosur->AnalysisContext->children_cache_->ArgsSpec->FuncGraphAbstactClosur.
|
||||
// For break the loop, using all_context_ to clear context_.
|
||||
// There may be shared_ptr loops in the form of:
|
||||
// FuncGraphAbstactClosure -> AnalysisContext -> children_cache_ -> ArgsSpec -> FuncGraphAbstactClosure.
|
||||
// To break the loop, use all_context_ to clear context_.
|
||||
static std::list<AnalysisContextPtr> all_context_;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ std::string ShapeVectorToStr(const std::vector<int64_t> &shp) {
|
|||
std::ostringstream buffer;
|
||||
bool f_begin = true;
|
||||
buffer << "(";
|
||||
|
||||
// Iterate through the elements of the shape vector.
|
||||
for (auto &x : shp) {
|
||||
if (!f_begin) {
|
||||
buffer << ", ";
|
||||
|
|
@ -50,9 +52,15 @@ std::ostream &operator<<(std::ostream &os, const std::shared_ptr<BaseShape> bs)
|
|||
return os;
|
||||
}
|
||||
|
||||
bool BaseShape::operator==(const BaseShape &other) const { return tid() == other.tid(); }
|
||||
bool BaseShape::operator==(const BaseShape &other) const {
|
||||
// Check if the type identifier of the shapes matches.
|
||||
return tid() == other.tid();
|
||||
}
|
||||
|
||||
bool BaseShape::operator!=(const BaseShape &other) const { return !(*this == other); }
|
||||
bool BaseShape::operator!=(const BaseShape &other) const {
|
||||
// Check if the type identifier of the shapes does not match.
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
std::string Shape::ToString() const {
|
||||
std::ostringstream buffer;
|
||||
|
|
@ -74,6 +82,8 @@ std::string Shape::ToString() const {
|
|||
std::string Shape::DumpText() const {
|
||||
std::ostringstream buffer;
|
||||
buffer << "[";
|
||||
|
||||
// Iterate through the shape elements and add them to the string representation.
|
||||
for (size_t i = 0; i < shape_.size(); i++) {
|
||||
buffer << (i > 0 ? ", " : "") << shape_[i];
|
||||
if (shape_[i] == SHP_ANY && min_shape_.size() == shape_.size() && max_shape_.size() == shape_.size()) {
|
||||
|
|
@ -99,7 +109,9 @@ bool Shape::operator==(const BaseShape &other) const {
|
|||
}
|
||||
|
||||
const int64_t Shape::SHP_ANY;
|
||||
|
||||
void Shape::Broaden() {
|
||||
// Set all elements of the shape to SHP_ANY.
|
||||
for (size_t i = 0; i < shape_.size(); i++) {
|
||||
shape_[i] = SHP_ANY;
|
||||
}
|
||||
|
|
@ -108,6 +120,8 @@ void Shape::Broaden() {
|
|||
std::string SequenceShape::ToString() const {
|
||||
std::ostringstream buffer;
|
||||
bool f_begin = true;
|
||||
|
||||
// Iterate through the elements of p_shapes_ and add them to the string representation.
|
||||
for (const auto &p_shp : p_shapes_) {
|
||||
if (!f_begin) {
|
||||
buffer << ", ";
|
||||
|
|
@ -122,6 +136,8 @@ std::string SequenceShape::ToString() const {
|
|||
|
||||
BaseShapePtrList SequenceShape::ElementsClone() const {
|
||||
BaseShapePtrList ele_list;
|
||||
|
||||
// Clone each element in p_shapes_ and add them to ele_list.
|
||||
for (auto p_shp : p_shapes_) {
|
||||
MS_EXCEPTION_IF_NULL(p_shp);
|
||||
ele_list.push_back(p_shp->Clone());
|
||||
|
|
@ -129,6 +145,7 @@ BaseShapePtrList SequenceShape::ElementsClone() const {
|
|||
return ele_list;
|
||||
}
|
||||
|
||||
// Explicit template instantiations for SequenceEqual.
|
||||
template bool SequenceShape::SequenceEqual<TupleShape>(const BaseShape &) const;
|
||||
template bool SequenceShape::SequenceEqual<ListShape>(const BaseShape &) const;
|
||||
} // namespace abstract
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
namespace mindspore {
|
||||
namespace abstract {
|
||||
// Define and initialize the ReportNameTraits for various Abstract types.
|
||||
#define ABSTRACT_REPORT_NAME_DEC(abstract) constexpr char ReportNameTraits<Abstract##abstract>::name[];
|
||||
|
||||
ABSTRACT_REPORT_NAME_DEC(Tensor)
|
||||
|
|
@ -39,6 +40,7 @@ ABSTRACT_REPORT_NAME_DEC(Type)
|
|||
ABSTRACT_REPORT_NAME_DEC(KeywordArg)
|
||||
ABSTRACT_REPORT_NAME_DEC(Class)
|
||||
|
||||
// Check if the type of 'type' matches one of the 'accepts' types.
|
||||
TypePtr CheckType(TypePtr type, const TypePtrList &accepts, const std::string &error_message_prefix) {
|
||||
auto ori_type = type;
|
||||
if (type->isa<TensorType>()) {
|
||||
|
|
@ -46,15 +48,18 @@ TypePtr CheckType(TypePtr type, const TypePtrList &accepts, const std::string &e
|
|||
type = tensor->element();
|
||||
MS_EXCEPTION_IF_NULL(type);
|
||||
}
|
||||
|
||||
// Check if 'type' is compatible with any of the 'accepts' types.
|
||||
bool ok = std::any_of(accepts.begin(), accepts.end(),
|
||||
[type](const TypePtr &accept) -> bool { return IsIdentidityOrSubclass(type, accept); });
|
||||
if (ok) {
|
||||
return type;
|
||||
} else {
|
||||
MS_EXCEPTION(TypeError) << error_message_prefix << " should be " << accepts << ",but got " << ori_type->ToString();
|
||||
MS_EXCEPTION(TypeError) << error_message_prefix << " should be " << accepts << ", but got " << ori_type->ToString();
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the dtype of 'tensor' matches one of the 'accepts' types.
|
||||
TypePtr CheckTensorDType(const AbstractTensorPtr &tensor, const TypePtrList &accepts,
|
||||
const std::string &error_message_prefix) {
|
||||
MS_EXCEPTION_IF_NULL(tensor);
|
||||
|
|
@ -66,6 +71,7 @@ TypePtr CheckTensorDType(const AbstractTensorPtr &tensor, const TypePtrList &acc
|
|||
return CheckType(type, accepts, error_message_prefix);
|
||||
}
|
||||
|
||||
// Check if the dtypes of all tensors in 'tensor_list' match one of the 'accepts' types.
|
||||
TypePtr CheckTensorsDTypeSame(const AbstractTensorPtrList &tensor_list, const TypePtrList &accepts,
|
||||
const std::string &error_message_prefix) {
|
||||
if (tensor_list.empty()) {
|
||||
|
|
@ -81,7 +87,8 @@ TypePtr CheckTensorsDTypeSame(const AbstractTensorPtrList &tensor_list, const Ty
|
|||
std::ostringstream loginfoBuffer;
|
||||
loginfoBuffer << "[" << sample_tensor->BuildType()->ToString();
|
||||
bool error_flag = false;
|
||||
// Check if other elements have the same type with the first element.
|
||||
|
||||
// Check if the dtypes of all tensors in 'tensor_list' match the dtype of the first tensor.
|
||||
for (size_t index = 1; index < tensor_list.size(); ++index) {
|
||||
MS_EXCEPTION_IF_NULL(tensor_list[index]);
|
||||
auto elem = tensor_list[index]->element();
|
||||
|
|
@ -94,12 +101,13 @@ TypePtr CheckTensorsDTypeSame(const AbstractTensorPtrList &tensor_list, const Ty
|
|||
}
|
||||
}
|
||||
if (error_flag) {
|
||||
MS_EXCEPTION(ValueError) << error_message_prefix << " must be same, but got " << loginfoBuffer.str() << "]";
|
||||
MS_EXCEPTION(ValueError) << error_message_prefix << " must be the same, but got " << loginfoBuffer.str() << "]";
|
||||
}
|
||||
MS_LOG(DEBUG) << error_message_prefix << loginfoBuffer.str();
|
||||
return CheckTensorDType(sample_tensor, accepts, error_message_prefix);
|
||||
}
|
||||
|
||||
// Check if the scalar's type matches one of the 'accepts' types.
|
||||
TypePtr CheckScalarType(const AbstractScalarPtr &scalar, const TypePtrList &accepts,
|
||||
const std::string &error_message_prefix) {
|
||||
if (scalar == nullptr) {
|
||||
|
|
@ -113,6 +121,7 @@ TypePtr CheckScalarType(const AbstractScalarPtr &scalar, const TypePtrList &acce
|
|||
return CheckType(type, accepts, error_message_prefix);
|
||||
}
|
||||
|
||||
// Check if the shapes of two tensors are the same.
|
||||
void CheckShapeSame(const std::string &op, const AbstractTensorPtr &tensor_base, const AbstractTensorPtr &tensor) {
|
||||
MS_EXCEPTION_IF_NULL(tensor_base);
|
||||
ShapePtr shape_base = tensor_base->shape();
|
||||
|
|
@ -128,7 +137,7 @@ void CheckShapeSame(const std::string &op, const AbstractTensorPtr &tensor_base,
|
|||
auto shape_base_vector = shape_base->shape();
|
||||
if (shape_vector.size() != shape_base_vector.size()) {
|
||||
MS_LOG(EXCEPTION) << op << " evaluator first arg shape " << shape->ToString()
|
||||
<< " are not consistent with second arg shape " << shape_base->ToString();
|
||||
<< " is not consistent with second arg shape " << shape_base->ToString();
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < shape_vector.size(); i++) {
|
||||
|
|
@ -137,12 +146,12 @@ void CheckShapeSame(const std::string &op, const AbstractTensorPtr &tensor_base,
|
|||
}
|
||||
if (shape_vector[i] != shape_base_vector[i]) {
|
||||
MS_LOG(EXCEPTION) << op << " evaluator first arg shape " << shape->ToString()
|
||||
<< " are not consistent with second arg shape " << shape_base->ToString();
|
||||
<< " is not consistent with second arg shape " << shape_base->ToString();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the dtype of two tensors is the same.
|
||||
TypePtr CheckDtypeSame(const std::string &op, const AbstractTensorPtr &tensor_base, const AbstractTensorPtr &tensor) {
|
||||
MS_EXCEPTION_IF_NULL(tensor_base);
|
||||
auto base_elem = tensor_base->element();
|
||||
|
|
@ -156,11 +165,12 @@ TypePtr CheckDtypeSame(const std::string &op, const AbstractTensorPtr &tensor_ba
|
|||
MS_EXCEPTION_IF_NULL(type);
|
||||
if (*type != *type_base) {
|
||||
MS_LOG(EXCEPTION) << op << " evaluator first arg dtype " << type_base->ToString()
|
||||
<< " are not consistent with second arg dtype " << type->ToString();
|
||||
<< " is not consistent with second arg dtype " << type->ToString();
|
||||
}
|
||||
return type_base;
|
||||
}
|
||||
|
||||
// Check if 'axis' is within the valid range.
|
||||
int64_t CheckAxis(const std::string &op, const std::string &args_name, const ValuePtr &axis, int64_t minimum,
|
||||
int64_t max, const std::string &rank_name) {
|
||||
if (axis == nullptr) {
|
||||
|
|
@ -180,6 +190,8 @@ int64_t CheckAxis(const std::string &op, const std::string &args_name, const Val
|
|||
}
|
||||
return axis_value;
|
||||
}
|
||||
|
||||
// Check if the number of input arguments matches 'size_expect'.
|
||||
void CheckArgsSize(const std::string &op, const mindspore::abstract::AbstractBasePtrList &args_spec_list,
|
||||
size_t size_expect) {
|
||||
if (args_spec_list.size() != size_expect) {
|
||||
|
|
@ -192,23 +204,26 @@ void CheckArgsSize(const std::string &op, const mindspore::abstract::AbstractBas
|
|||
}
|
||||
}
|
||||
|
||||
// Check if all elements in 'shape' are positive integers.
|
||||
void CheckShapeAllPositive(const std::string &op, const ShapeVector &shape) {
|
||||
for (size_t i = 0; i < shape.size(); ++i) {
|
||||
if (shape[i] < 0) {
|
||||
MS_LOG(EXCEPTION) << op << " shape element [" << i << "] must be positive integer, but got " << shape[i];
|
||||
MS_LOG(EXCEPTION) << op << " shape element [" << i << "] must be a positive integer, but got " << shape[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if all elements in 'shape' are either positive integers or SHP_ANY.
|
||||
void CheckShapeAnyAndPositive(const std::string &op, const ShapeVector &shape) {
|
||||
for (size_t i = 0; i < shape.size(); ++i) {
|
||||
if ((shape[i] < 0) && (shape[i] != Shape::SHP_ANY)) {
|
||||
MS_EXCEPTION(ValueError) << op << " shape element [" << i << "] must be positive integer or SHP_ANY, but got "
|
||||
MS_EXCEPTION(ValueError) << op << " shape element [" << i << "] must be a positive integer or SHP_ANY, but got "
|
||||
<< shape[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the number of input arguments is at least 'size_expect'.
|
||||
void CheckRequiredArgsSize(const std::string &op, const mindspore::abstract::AbstractBasePtrList &args_spec_list,
|
||||
size_t size_expect) {
|
||||
if (args_spec_list.size() < size_expect) {
|
||||
|
|
|
|||
|
|
@ -30,37 +30,99 @@
|
|||
|
||||
namespace mindspore {
|
||||
namespace abstract {
|
||||
// check if variable's type is an instance of any of accepts or of a subclass of it.
|
||||
/// \brief Checks if the given type is an instance of any of the accepted types or a subclass of them.
|
||||
/// \param[in] type: The TypePtr to check.
|
||||
/// \param[in] accepts: A list of accepted types.
|
||||
/// \param[in] error_message_prefix: A prefix to use in error messages if the check fails.
|
||||
/// \return The input type if it is valid; otherwise, raises an error.
|
||||
TypePtr CheckType(TypePtr type, const TypePtrList &accepts, const std::string &error_message_prefix);
|
||||
|
||||
/// \brief Checks the data type of a tensor against a list of accepted types.
|
||||
/// \param[in] tensor: The AbstractTensorPtr to check.
|
||||
/// \param[in] accepts: A list of accepted data types.
|
||||
/// \param[in] error_message_prefix: A prefix to use in error messages if the check fails.
|
||||
/// \return The data type of the input tensor if it is valid; otherwise, raises an error.
|
||||
TypePtr CheckTensorDType(const AbstractTensorPtr &tensor, const TypePtrList &accepts,
|
||||
const std::string &error_message_prefix);
|
||||
|
||||
/// \brief Checks that the data types of a list of tensors are the same and within the accepted types.
|
||||
/// \param[in] tensor_list: A list of AbstractTensorPtr to check.
|
||||
/// \param[in] accepts: A list of accepted data types.
|
||||
/// \param[in] error_message_prefix: A prefix to use in error messages if the check fails.
|
||||
/// \return The data type of the input tensors if they are valid; otherwise, raises an error.
|
||||
TypePtr CheckTensorsDTypeSame(const AbstractTensorPtrList &tensor_list, const TypePtrList &accepts,
|
||||
const std::string &error_message_prefix);
|
||||
|
||||
/// \brief Checks the data type of a scalar against a list of accepted types.
|
||||
/// \param[in] scalar: The AbstractScalarPtr to check.
|
||||
/// \param[in] accepts: A list of accepted data types.
|
||||
/// \param[in] error_message_prefix: A prefix to use in error messages if the check fails.
|
||||
/// \return The data type of the input scalar if it is valid; otherwise, raises an error.
|
||||
TypePtr CheckScalarType(const AbstractScalarPtr &scalar, const TypePtrList &accepts,
|
||||
const std::string &error_message_prefix);
|
||||
|
||||
/// \brief Checks that the shapes of two tensors are the same.
|
||||
/// \param[in] op: The name of the operation.
|
||||
/// \param[in] tensor_base: The first AbstractTensorPtr to compare.
|
||||
/// \param[in] tensor: The second AbstractTensorPtr to compare.
|
||||
void CheckShapeSame(const std::string &op, const AbstractTensorPtr &tensor_base, const AbstractTensorPtr &tensor);
|
||||
|
||||
/// \brief Checks that the data types of two tensors are the same.
|
||||
/// \param[in] op: The name of the operation.
|
||||
/// \param[in] tensor_base: The first AbstractTensorPtr to compare.
|
||||
/// \param[in] tensor: The second AbstractTensorPtr to compare.
|
||||
/// \return The data type of the input tensors if they are valid; otherwise, raises an error.
|
||||
TypePtr CheckDtypeSame(const std::string &op, const AbstractTensorPtr &tensor_base, const AbstractTensorPtr &tensor);
|
||||
|
||||
/// \brief Checks the axis value within a specified range.
|
||||
/// \param[in] op: The name of the operation.
|
||||
/// \param[in] arg_name: The name of the argument.
|
||||
/// \param[in] axis: The ValuePtr representing the axis to check.
|
||||
/// \param[in] min: The minimum valid axis value.
|
||||
/// \param[in] max: The maximum valid axis value.
|
||||
/// \param[in] rank_name: The name of the rank argument for error messages.
|
||||
/// \return The valid axis value.
|
||||
MS_CORE_API int64_t CheckAxis(const std::string &op, const std::string &arg_name, const ValuePtr &axis, int64_t min,
|
||||
int64_t max, const std::string &rank_name);
|
||||
|
||||
MS_CORE_API void CheckArgsSize(const std::string &op, const AbstractBasePtrList &args_spec_list, size_t size_expect);
|
||||
/// \brief Checks the size of a list of arguments.
|
||||
/// \param[in] op: The name of the operation.
|
||||
/// \param[in] args_spec_list: The list of AbstractBasePtr to check.
|
||||
/// \param[in] size_expect: The expected size of the list.
|
||||
void CheckArgsSize(const std::string &op, const AbstractBasePtrList &args_spec_list, size_t size_expect);
|
||||
|
||||
/// \brief Checks that all values in the given shape are positive.
|
||||
/// \param[in] op: The name of the operation.
|
||||
/// \param[in] shape: The shape to check.
|
||||
void CheckShapeAllPositive(const std::string &op, const ShapeVector &shape);
|
||||
|
||||
/// \brief Checks that at least one value in the given shape is positive.
|
||||
/// \param[in] op: The name of the operation.
|
||||
/// \param[in] shape: The shape to check.
|
||||
void CheckShapeAnyAndPositive(const std::string &op, const ShapeVector &shape);
|
||||
|
||||
/// \brief Checks if the attribute is an integer or a tuple of integers.
|
||||
/// \param[in] op: The name of the operation.
|
||||
/// \param[in] attr: The ValuePtr representing the attribute to check.
|
||||
/// \param[in] start_idx: The starting index of the attribute elements in case it's a tuple.
|
||||
/// \param[in] num_element: The number of elements to check.
|
||||
/// \return A vector of integers extracted from the attribute.
|
||||
std::vector<int64_t> CheckAttrIntOrTuple(const std::string &op, const ValuePtr &attr, const size_t start_idx,
|
||||
const size_t num_element);
|
||||
|
||||
/// \brief Checks if the attribute is a string within a set of valid values.
|
||||
/// \param[in] op: The name of the operation.
|
||||
/// \param[in] attr: The ValuePtr representing the attribute to check.
|
||||
/// \param[in] attr_name: The name of the attribute for error messages.
|
||||
/// \param[in] val_set: A set of valid string values.
|
||||
/// \return The valid string attribute value.
|
||||
std::string CheckAttrStringSet(const std::string &op, const ValuePtr &attr, const std::string &attr_name,
|
||||
const std::set<std::string> &val_set);
|
||||
|
||||
/// \brief Checks the size of a list of required arguments.
|
||||
/// \param[in] op: The name of the operation.
|
||||
/// \param[in] args_spec_list: The list of AbstractBasePtr to check.
|
||||
/// \param[in] size_expect: The expected size of the list.
|
||||
void CheckRequiredArgsSize(const std::string &op, const AbstractBasePtrList &args_spec_list, size_t size_expect);
|
||||
|
||||
template <typename T>
|
||||
|
|
|
|||
|
|
@ -45,9 +45,16 @@
|
|||
|
||||
namespace mindspore {
|
||||
namespace abstract {
|
||||
// Function that returns a set of integers representing dependencies based on a primitive's name and input number.
|
||||
// Parameters:
|
||||
// - prim_name: A string representing the name of the primitive.
|
||||
// - input_num: The number of inputs to the primitive.
|
||||
// Returns:
|
||||
// - A set of integers representing the dependencies.
|
||||
std::set<int64_t> GetDependsFormMap(const std::string &prim_name, size_t input_num) {
|
||||
using ShapeSet = std::set<int64_t>;
|
||||
using PrimShapeDependMap = mindspore::HashMap<std::string, ShapeSet>;
|
||||
// Static mapping of primitive names to sets of integers representing dependencies.
|
||||
static const auto &kOneHot = prim::kPrimOneHot->name();
|
||||
static const auto &kDropoutGenMask = prim::kPrimDropoutGenMask->name();
|
||||
static const auto &kTranspose = prim::kPrimTranspose->name();
|
||||
|
|
@ -71,6 +78,7 @@ std::set<int64_t> GetDependsFormMap(const std::string &prim_name, size_t input_n
|
|||
static const auto &kReshape = prim::kPrimReshape->name();
|
||||
static const auto &kFillV2 = prim::kPrimFillV2->name();
|
||||
// Common dynamic shape depends.
|
||||
// Define a map of dependencies for specific primitives.
|
||||
static const PrimShapeDependMap dynamic_shape_depends{{kUnsortedSegmentSum, ShapeSet{2}},
|
||||
{kUnsortedSegmentMin, ShapeSet{2}},
|
||||
{kUnsortedSegmentMax, ShapeSet{2}},
|
||||
|
|
@ -97,10 +105,11 @@ std::set<int64_t> GetDependsFormMap(const std::string &prim_name, size_t input_n
|
|||
MS_EXCEPTION_IF_NULL(ms_context);
|
||||
auto device = ms_context->get_param<std::string>(MS_CTX_DEVICE_TARGET);
|
||||
// Special dynamic shape depends for Ascend.
|
||||
// Special case for dynamic shape depends on Ascend device for the 'Transpose' primitive.
|
||||
if (device == kAscendDevice && prim_name == kTranspose) {
|
||||
return {1};
|
||||
}
|
||||
|
||||
// Look up the primitive name in the map and filter dependencies based on input number.
|
||||
auto iter = dynamic_shape_depends.find(prim_name);
|
||||
if (iter != dynamic_shape_depends.end()) {
|
||||
ShapeSet res;
|
||||
|
|
@ -111,7 +120,11 @@ std::set<int64_t> GetDependsFormMap(const std::string &prim_name, size_t input_n
|
|||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
// Function that returns a set of integers representing dependencies based on a CNode.
|
||||
// Parameters:
|
||||
// - cnode: A CNodePtr representing the computation node.
|
||||
// Returns:
|
||||
// - A set of integers representing the dependencies.
|
||||
std::set<int64_t> GetDependsFormMap(const CNodePtr &cnode) {
|
||||
MS_EXCEPTION_IF_NULL(cnode);
|
||||
if (cnode->inputs().empty()) {
|
||||
|
|
@ -122,9 +135,11 @@ std::set<int64_t> GetDependsFormMap(const CNodePtr &cnode) {
|
|||
auto prim_name = primitive->ToString();
|
||||
return GetDependsFormMap(prim_name, cnode->inputs().size() - 1);
|
||||
}
|
||||
|
||||
// Function that provides a mapping between primitives and their shape and value inference implementations.
|
||||
// - A map where primitive names (keys) are mapped to their corresponding inference implementations (values).
|
||||
PrimitiveEvalImplMap &GetPrimitiveToEvalImplMap() {
|
||||
using R = PrimitiveEvalImplMap::mapped_type;
|
||||
// Static mapping between primitive names and their inference implementations.
|
||||
static PrimitiveEvalImplMap prim_eval_implement_map{
|
||||
// Statements
|
||||
{prim::kPrimReturn, R{InferImplReturn, nullptr, true}},
|
||||
|
|
@ -259,9 +274,12 @@ PrimitiveEvalImplMap &GetPrimitiveToEvalImplMap() {
|
|||
};
|
||||
return prim_eval_implement_map;
|
||||
}
|
||||
|
||||
// Function that provides a mapping between primitives and their backend shape and value inference implementations.
|
||||
// Returns:
|
||||
// - A map where primitive names (keys) are mapped to their corresponding backend inference implementations (values).
|
||||
PrimitiveEvalImplMap &GetPrimitiveToBackendEvalImplMap() {
|
||||
using R = PrimitiveEvalImplMap::mapped_type;
|
||||
// Static mapping between primitive names and their backend inference implementations.
|
||||
static PrimitiveEvalImplMap prim_backend_eval_implement_map = {
|
||||
{prim::kPrimMul, R{ops::MulInfer, nullptr, true}},
|
||||
{prim::kPrimMod, R{ops::ModInfer, nullptr, true}},
|
||||
|
|
@ -314,7 +332,11 @@ PrimitiveEvalImplMap &GetPrimitiveToBackendEvalImplMap() {
|
|||
};
|
||||
return prim_backend_eval_implement_map;
|
||||
}
|
||||
|
||||
// Function that retrieves the shape and value inference implementations for a given primitive.
|
||||
// Parameters:
|
||||
// - primitive: A PrimitivePtr representing the primitive for which to retrieve the implementations.
|
||||
// Returns:
|
||||
// - A StandardPrimitiveImplReg struct containing the inference implementations and a flag indicating if it's in the white list.
|
||||
StandardPrimitiveImplReg GetPrimitiveInferImpl(const PrimitivePtr &primitive) {
|
||||
MS_EXCEPTION_IF_NULL(primitive);
|
||||
auto iter = GetPrimitiveToEvalImplMap().find(primitive);
|
||||
|
|
@ -323,7 +345,10 @@ StandardPrimitiveImplReg GetPrimitiveInferImpl(const PrimitivePtr &primitive) {
|
|||
}
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
// Function to register shape and value inference implementations for a primitive.
|
||||
// Parameters:
|
||||
// - primitive: A PrimitivePtr representing the primitive for which to register the implementations.
|
||||
// - impl_reg: A StandardPrimitiveImplReg struct containing the inference implementations and a flag indicating if it's in the white list.
|
||||
void RegisterStandardPrimitiveImpl(const PrimitivePtr &primitive, const StandardPrimitiveImplReg &impl_reg) {
|
||||
auto &prim_eval_map = GetPrimitiveToEvalImplMap();
|
||||
prim_eval_map[primitive] = impl_reg;
|
||||
|
|
|
|||
|
|
@ -31,33 +31,52 @@
|
|||
|
||||
namespace mindspore {
|
||||
namespace abstract {
|
||||
|
||||
// Define function pointer types for shape and value inference for primitives.
|
||||
using InferShapeImpl = AbstractBasePtr (*)(const abstract::AnalysisEnginePtr &, const PrimitivePtr &,
|
||||
const AbstractBasePtrList &);
|
||||
using InferValueImpl = ValuePtr (*)(const PrimitivePtr &, const AbstractBasePtrList &);
|
||||
|
||||
// Structure to register shape and value inference implementations for primitives.
|
||||
struct StandardPrimitiveImplReg {
|
||||
InferShapeImpl infer_shape_impl_; // infer shape and type for ops
|
||||
InferValueImpl infer_value_impl_; // infer value for ops
|
||||
// in_white_list_ is true means this primitive can be executed by vm backend
|
||||
// else will be optimized by frontend
|
||||
bool in_white_list_;
|
||||
InferShapeImpl infer_shape_impl_; // Function pointer for shape inference.
|
||||
InferValueImpl infer_value_impl_; // Function pointer for value inference.
|
||||
bool in_white_list_; // Indicates if the primitive is in the white list for execution by the VM backend.
|
||||
};
|
||||
|
||||
// Define a mapping between primitives and their shape and value inference implementations.
|
||||
using PrimitiveEvalImplMap =
|
||||
mindspore::HashMap<PrimitivePtr, StandardPrimitiveImplReg, PrimitiveHasher, PrimitiveEqual>;
|
||||
|
||||
/// \brief Provides a mapping between primitives and their shape and value inference implementations.
|
||||
/// \return A map where primitive names (keys) are mapped to their corresponding inference implementations (values).
|
||||
MS_CORE_API PrimitiveEvalImplMap &GetPrimitiveToEvalImplMap();
|
||||
|
||||
/// \brief Provides a mapping between primitives and their backend shape and value inference implementations.
|
||||
/// \return A map where primitive names (keys) are mapped to their corresponding backend inference implementations (values).
|
||||
MS_CORE_API PrimitiveEvalImplMap &GetPrimitiveToBackendEvalImplMap();
|
||||
|
||||
|
||||
/// \brief Retrieves the shape and value inference implementations for a given primitive.
|
||||
/// \param[in] primitive: A PrimitivePtr representing the primitive for which to retrieve the implementations.
|
||||
/// \return A StandardPrimitiveImplReg struct containing the inference implementations and a flag indicating if it's in the white list.
|
||||
MS_CORE_API StandardPrimitiveImplReg GetPrimitiveInferImpl(const PrimitivePtr &primitive);
|
||||
|
||||
/// \brief get dependencies from a map for a given primitive name and input number.
|
||||
/// \return A map where primitive names (keys) are mapped to their corresponding inference implementations (values).
|
||||
MS_CORE_API std::set<int64_t> GetDependsFormMap(const std::string &prim_name, size_t input_num);
|
||||
|
||||
/// \brief Get dependencies based on a CNode.
|
||||
/// \param[in] cnode: A CNodePtr representing the computation node.
|
||||
/// \return A set of integers representing the dependencies.
|
||||
MS_CORE_API std::set<int64_t> GetDependsFormMap(const CNodePtr &cnode);
|
||||
|
||||
/// \brief Registers shape and value inference implementations for a primitive.
|
||||
/// \param[in] primitive: A PrimitivePtr representing the primitive for which to register the implementations.
|
||||
/// \param[in] impl_reg: A StandardPrimitiveImplReg struct containing the inference implementations and a flag indicating if it's in the white list
|
||||
MS_CORE_API void RegisterStandardPrimitiveImpl(const PrimitivePtr &primitive, const StandardPrimitiveImplReg &impl_reg);
|
||||
|
||||
// Helper class for registering shape and value inference implementations for primitives.
|
||||
class RegisterStandardPrimitiveEvalHelper {
|
||||
public:
|
||||
RegisterStandardPrimitiveEvalHelper(const PrimitivePtr &primitive, const InferShapeImpl &infer_impl,
|
||||
|
|
@ -68,6 +87,7 @@ class RegisterStandardPrimitiveEvalHelper {
|
|||
~RegisterStandardPrimitiveEvalHelper() = default;
|
||||
};
|
||||
|
||||
// Macro to simplify the registration of shape and value inference implementations for primitives.
|
||||
#define REGISTER_PRIMITIVE_EVAL_IMPL(name, primitive, infer_impl, infer_value_impl, is_white_list) \
|
||||
static auto helper_##name = \
|
||||
abstract::RegisterStandardPrimitiveEvalHelper(primitive, infer_impl, infer_value_impl, is_white_list); \
|
||||
|
|
@ -78,4 +98,4 @@ class RegisterStandardPrimitiveEvalHelper {
|
|||
ops::OpPrimCRegisterHelper primc_gen_##name(#name, GetDefaultPrimC##name);
|
||||
} // namespace abstract
|
||||
} // namespace mindspore
|
||||
#endif // MINDSPORE_CORE_ABSTRACT_PRIMITIVE_INFER_MAP_H_
|
||||
#endif // MINDSPORE_CORE_ABSTRACT_PRIMITIVE_INFER_MAP_H_
|
||||
|
|
@ -24,33 +24,36 @@
|
|||
|
||||
namespace mindspore {
|
||||
namespace abstract {
|
||||
// A mapping of MindSpore data types to their sizes in bytes
|
||||
const std::map<TypeId, size_t> type_map = {
|
||||
{kNumberTypeBool, 1}, {kNumberTypeInt, 4}, {kNumberTypeInt8, 1}, {kNumberTypeInt16, 2},
|
||||
{kNumberTypeInt32, 4}, {kNumberTypeInt64, 8}, {kNumberTypeUInt, 4}, {kNumberTypeUInt8, 1},
|
||||
{kNumberTypeUInt16, 2}, {kNumberTypeUInt32, 4}, {kNumberTypeUInt64, 8}, {kNumberTypeFloat, 4},
|
||||
{kNumberTypeFloat16, 2}, {kNumberTypeFloat32, 4}, {kNumberTypeFloat64, 8}, {kNumberTypeComplex64, 8},
|
||||
{kNumberTypeComplex128, 16}};
|
||||
|
||||
ValuePtr ValueJoin(const ValuePtr &value1, const ValuePtr &value2) {
|
||||
MS_EXCEPTION_IF_NULL(value1);
|
||||
MS_EXCEPTION_IF_NULL(value2);
|
||||
if (*value1 == *value2) {
|
||||
return value1;
|
||||
return value1;
|
||||
}
|
||||
return kAnyValue;
|
||||
}
|
||||
|
||||
// Join two Type objects
|
||||
TypePtr TypeJoin(const TypePtr &type1, const TypePtr &type2) {
|
||||
MS_EXCEPTION_IF_NULL(type1);
|
||||
MS_EXCEPTION_IF_NULL(type2);
|
||||
// If the two types are equal, return one of them
|
||||
if (*type1 == *type2) {
|
||||
return type1;
|
||||
}
|
||||
// Otherwise, return a generic "Any" type
|
||||
return kAnyType;
|
||||
}
|
||||
|
||||
// Calculate the dynamic shape based on two shapes and a vector of dimensions
|
||||
ShapePtr CalculateDynamicShape(const ShapePtr &shape1, const ShapePtr &shape2, const ShapeVector &dims) {
|
||||
// calculate dynamic shape
|
||||
// Initialize min_dims and max_dims with the provided dimensions
|
||||
ShapeVector min_dims(dims.size());
|
||||
ShapeVector max_dims(dims.size());
|
||||
MS_EXCEPTION_IF_NULL(shape1);
|
||||
|
|
@ -83,7 +86,7 @@ ShapePtr CalculateDynamicShape(const ShapePtr &shape1, const ShapePtr &shape2, c
|
|||
max_dims[i] = std::max(shape1->shape()[i], shape2->max_shape()[i]);
|
||||
continue;
|
||||
}
|
||||
// both shapes contains dynamic shape
|
||||
// Both shapes contain dynamic shape
|
||||
if (shape1->min_shape().size() <= i || shape1->max_shape().size() <= i) {
|
||||
MS_EXCEPTION(ValueError) << "Shape " << shape1->ToString()
|
||||
<< " has dynamic shape, but does not have min/max shape info.";
|
||||
|
|
@ -95,18 +98,21 @@ ShapePtr CalculateDynamicShape(const ShapePtr &shape1, const ShapePtr &shape2, c
|
|||
min_dims[i] = std::min(shape1->min_shape()[i], shape2->min_shape()[i]);
|
||||
max_dims[i] = std::max(shape1->max_shape()[i], shape2->max_shape()[i]);
|
||||
}
|
||||
// Create a new Shape object with the calculated dynamic shape
|
||||
return std::make_shared<Shape>(dims, min_dims, max_dims);
|
||||
}
|
||||
|
||||
// Join two Shape objects
|
||||
ShapePtr ShapeJoin(const ShapePtr &shape1, const ShapePtr &shape2) {
|
||||
MS_EXCEPTION_IF_NULL(shape1);
|
||||
MS_EXCEPTION_IF_NULL(shape2);
|
||||
// If the two shapes are equal, return one of them
|
||||
if (*shape1 == *shape2) {
|
||||
return shape1;
|
||||
}
|
||||
// lengths of two shapes are not same, join failed
|
||||
// If the lengths of the two shapes are not the same, join failed
|
||||
if (shape1->shape().size() != shape2->shape().size()) {
|
||||
// special case: shape(1), shape() -> shape(1)
|
||||
// Special case: shape(1), shape() -> shape(1)
|
||||
if (shape1->shape().size() == 1 && shape1->shape()[0] == 1 && shape2->shape().empty()) {
|
||||
return shape1;
|
||||
}
|
||||
|
|
@ -130,35 +136,41 @@ ShapePtr ShapeJoin(const ShapePtr &shape1, const ShapePtr &shape2) {
|
|||
}
|
||||
}
|
||||
if (!has_dynamic_shape) {
|
||||
// If there are no dynamic shapes, return a new Shape with the calculated dimensions
|
||||
return std::make_shared<Shape>(dims);
|
||||
}
|
||||
// If there are dynamic shapes, calculate the dynamic shape based on the two shapes and dimensions
|
||||
return CalculateDynamicShape(shape1, shape2, dims);
|
||||
}
|
||||
|
||||
// Join a list of AbstractBasePtr objects
|
||||
AbstractBasePtr AbstractJoin(const AbstractBasePtrList &args_spec_list) {
|
||||
if (args_spec_list.empty()) {
|
||||
MS_LOG(EXCEPTION) << "AbstractJoin requires at least 1 params, while the input size is " << args_spec_list.size()
|
||||
MS_LOG(EXCEPTION) << "AbstractJoin requires at least 1 parameter, but the input size is " << args_spec_list.size()
|
||||
<< ".";
|
||||
}
|
||||
AbstractBasePtr arg_spec_tmp = args_spec_list[0];
|
||||
MS_EXCEPTION_IF_NULL(arg_spec_tmp);
|
||||
for (const auto &arg_spec : args_spec_list) {
|
||||
MS_EXCEPTION_IF_NULL(arg_spec);
|
||||
// Join the AbstractBasePtr objects to create a new one
|
||||
arg_spec_tmp = arg_spec_tmp->Join(arg_spec);
|
||||
MS_EXCEPTION_IF_NULL(arg_spec_tmp);
|
||||
}
|
||||
return arg_spec_tmp;
|
||||
}
|
||||
|
||||
// Join two lists of AbstractBasePtr objects
|
||||
AbstractBasePtrList AbstractJoin(const AbstractBasePtrList &spec1, const AbstractBasePtrList &spec2) {
|
||||
if (spec1.size() != spec2.size()) {
|
||||
MS_LOG(EXCEPTION) << "Join failed as list don't have the same size. spec1: " << ::mindspore::ToString(spec1)
|
||||
<< ", spec2: " << ::mindspore::ToString(spec2);
|
||||
MS_LOG(EXCEPTION) << "Join failed because the lists do not have the same size. spec1: "
|
||||
<< ::mindspore::ToString(spec1) << ", spec2: " << ::mindspore::ToString(spec2);
|
||||
}
|
||||
AbstractBasePtrList joined_list;
|
||||
bool changes = false;
|
||||
for (std::size_t i = 0; i < spec1.size(); i++) {
|
||||
MS_EXCEPTION_IF_NULL(spec1[i]);
|
||||
// Join each pair of AbstractBasePtr objects in the lists
|
||||
auto joined_elem = spec1[i]->Join(spec2[i]);
|
||||
MS_EXCEPTION_IF_NULL(joined_elem);
|
||||
if (joined_elem != spec1[i]) {
|
||||
|
|
@ -167,20 +179,28 @@ AbstractBasePtrList AbstractJoin(const AbstractBasePtrList &spec1, const Abstrac
|
|||
joined_list.push_back(joined_elem);
|
||||
}
|
||||
if (!changes) {
|
||||
// If there are no changes, return spec1
|
||||
return spec1;
|
||||
}
|
||||
// Otherwise, return the joined_list
|
||||
return joined_list;
|
||||
}
|
||||
|
||||
// Transform an AbstractBasePtr into its sensitivity
|
||||
AbstractBasePtr SensitivityTransform(const AbstractBasePtr &spec) {
|
||||
// Check if the spec is an AbstractFunction
|
||||
AbstractFunctionPtr f_spec = dyn_cast<AbstractFunction>(spec);
|
||||
if (f_spec != nullptr) {
|
||||
// If it is, return an AbstractScalar with "AnyValue" and an EnvType
|
||||
return std::make_shared<AbstractScalar>(kAnyValue, std::make_shared<EnvType>());
|
||||
}
|
||||
// Otherwise, return a clone of the spec
|
||||
return spec->Clone();
|
||||
}
|
||||
|
||||
// Broadcast two ShapeVectors to have the same dimensions
|
||||
ShapeVector BroadcastShape(ShapeVector shpx, ShapeVector shpy) {
|
||||
// Calculate the difference in dimensions
|
||||
int dlen = SizeToInt(shpx.size()) - SizeToInt(shpy.size());
|
||||
if (dlen < 0) {
|
||||
for (int i = 0; i < -dlen; ++i) {
|
||||
|
|
@ -191,6 +211,7 @@ ShapeVector BroadcastShape(ShapeVector shpx, ShapeVector shpy) {
|
|||
(void)shpy.insert(shpy.begin(), 1);
|
||||
}
|
||||
}
|
||||
// Check if the two ShapeVectors have the same size
|
||||
if (shpx.size() != shpy.size()) {
|
||||
MS_LOG(EXCEPTION) << "Failure: shpx.size() != shpy.size().";
|
||||
}
|
||||
|
|
@ -209,26 +230,34 @@ ShapeVector BroadcastShape(ShapeVector shpx, ShapeVector shpy) {
|
|||
} else if (a == b) {
|
||||
shp.push_back(a);
|
||||
} else {
|
||||
// If dimensions are incompatible, return an empty ShapeVector
|
||||
return ShapeVector();
|
||||
}
|
||||
}
|
||||
// Return the broadcasted ShapeVector
|
||||
return shp;
|
||||
}
|
||||
|
||||
// Get the size in bytes for a given data type
|
||||
size_t TypeIdSize(const TypeId data_type) {
|
||||
const size_t unsupported_type_error = 0;
|
||||
auto iter = type_map.find(data_type);
|
||||
if (iter != type_map.end()) {
|
||||
return iter->second;
|
||||
}
|
||||
// If the data type is not in the map, return 0 (unsupported type)
|
||||
return unsupported_type_error;
|
||||
}
|
||||
|
||||
// Check and update the minimum and maximum shapes based on a new shape
|
||||
void CheckMinMaxShape(const ShapeVector &shape, ShapeVector *min_shape, ShapeVector *max_shape) {
|
||||
// If min_shape is empty, set it to the new shape
|
||||
*min_shape = (*min_shape).empty() ? shape : *min_shape;
|
||||
// If max_shape is empty, set it to the new shape
|
||||
*max_shape = (*max_shape).empty() ? shape : *max_shape;
|
||||
}
|
||||
|
||||
// Create an AbstractTensor with the given shape and type
|
||||
AbstractBasePtr MakeAbstractTensor(const ShapePtr &shape, const TypePtr &type) {
|
||||
MS_EXCEPTION_IF_NULL(shape);
|
||||
MS_EXCEPTION_IF_NULL(type);
|
||||
|
|
@ -254,18 +283,22 @@ AbstractBasePtr MakeAbstractTensor(const ShapePtr &shape, const TypePtr &type) {
|
|||
auto element = std::make_shared<abstract::AbstractScalar>(kAnyValue, type);
|
||||
tensor = std::make_shared<abstract::AbstractTensor>(element, ret_shape);
|
||||
}
|
||||
// Return the created AbstractTensor
|
||||
return tensor;
|
||||
}
|
||||
|
||||
// Create a Monad abstract based on the given MonadType
|
||||
AbstractBasePtr MakeMonadAbstract(const MonadTypePtr &type) {
|
||||
if (type->isa<UMonadType>()) {
|
||||
return kUMonad->ToAbstract();
|
||||
} else if (type->isa<IOMonadType>()) {
|
||||
return kIOMonad->ToAbstract();
|
||||
}
|
||||
// Raise an exception for unsupported MonadType
|
||||
MS_EXCEPTION(UnknownError) << "Unsupported to convert type " << type->ToString() << " to monad abstract";
|
||||
}
|
||||
|
||||
// Create an AbstractBasePtr based on a BaseShapePtr and a TypePtr
|
||||
AbstractBasePtr MakeAbstract(const BaseShapePtr &base_shape, const TypePtr &type) {
|
||||
MS_EXCEPTION_IF_NULL(base_shape);
|
||||
MS_EXCEPTION_IF_NULL(type);
|
||||
|
|
@ -273,11 +306,12 @@ AbstractBasePtr MakeAbstract(const BaseShapePtr &base_shape, const TypePtr &type
|
|||
auto shape = base_shape->cast<ShapePtr>();
|
||||
MS_EXCEPTION_IF_NULL(shape);
|
||||
auto shape_vec = shape->shape();
|
||||
// if the size of shape list is empty, return an scalar abstract
|
||||
// If the size of shape list is empty and the type is not TensorType, return an AbstractScalar
|
||||
if (shape_vec.empty() && (!type->isa<TensorType>())) {
|
||||
abstract::AbstractScalarPtr abs_scalar = std::make_shared<abstract::AbstractScalar>(kAnyValue, type);
|
||||
return abs_scalar;
|
||||
}
|
||||
// Create an AbstractTensor based on the given shape and type
|
||||
return MakeAbstractTensor(shape, type);
|
||||
} else if (base_shape->isa<TupleShape>() && type->isa<Tuple>()) {
|
||||
auto shape_tuple = base_shape->cast<TupleShapePtr>();
|
||||
|
|
@ -287,6 +321,7 @@ AbstractBasePtr MakeAbstract(const BaseShapePtr &base_shape, const TypePtr &type
|
|||
auto tensor_it = MakeAbstract((*shape_tuple)[it], (*type_tuple)[it]);
|
||||
ptr_list.push_back(tensor_it);
|
||||
}
|
||||
// Create an AbstractTuple based on the given list of AbstractBasePtr
|
||||
auto tuple = std::make_shared<abstract::AbstractTuple>(ptr_list);
|
||||
return tuple;
|
||||
} else if (base_shape->isa<ListShape>() && type->isa<List>()) {
|
||||
|
|
@ -297,6 +332,7 @@ AbstractBasePtr MakeAbstract(const BaseShapePtr &base_shape, const TypePtr &type
|
|||
auto tensor_it = MakeAbstract((*shape_list)[it], (*type_list)[it]);
|
||||
ptr_list.push_back(tensor_it);
|
||||
}
|
||||
// Create an AbstractList based on the given list of AbstractBasePtr
|
||||
auto list = std::make_shared<abstract::AbstractList>(ptr_list);
|
||||
return list;
|
||||
} else if (base_shape->isa<NoShape>() && type->isa<TypeNone>()) {
|
||||
|
|
@ -304,18 +340,20 @@ AbstractBasePtr MakeAbstract(const BaseShapePtr &base_shape, const TypePtr &type
|
|||
auto abstract_none = std::make_shared<abstract::AbstractNone>();
|
||||
return abstract_none;
|
||||
} else if (type->isa<Monad>()) {
|
||||
// Return monad abstract if it is monad type.
|
||||
// Return a Monad abstract if it is a MonadType
|
||||
return MakeMonadAbstract(type->cast<MonadTypePtr>());
|
||||
} else {
|
||||
// When sparse enabled, the undetermined might be raised and eliminated in opt passes
|
||||
// When sparse is enabled, the "Undetermined" type might be raised and eliminated in optimization passes
|
||||
auto context = MsContext::GetInstance();
|
||||
MS_EXCEPTION_IF_NULL(context);
|
||||
bool enable_sparse = context->get_param<bool>(MS_CTX_ENABLE_SPARSE);
|
||||
if (enable_sparse) {
|
||||
return std::make_shared<abstract::AbstractUndetermined>();
|
||||
}
|
||||
MS_LOG(EXCEPTION) << "evaluator return invalid shape " << base_shape->ToString() << "or type. " << type->ToString();
|
||||
MS_LOG(EXCEPTION) << "Evaluator returned an invalid shape " << base_shape->ToString() << " or type "
|
||||
<< type->ToString();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace abstract
|
||||
} // namespace mindspore
|
||||
} // namespace mindspore
|
||||
|
|
@ -32,32 +32,102 @@
|
|||
|
||||
namespace mindspore {
|
||||
namespace abstract {
|
||||
|
||||
/// \brief Joins two values.
|
||||
|
||||
/// \param[in] value1: The first ValuePtr to join.
|
||||
/// \param[in] value2: The second ValuePtr to join.
|
||||
|
||||
/// \return A ValuePtr representing the result of joining value1 and value2.
|
||||
ValuePtr ValueJoin(const ValuePtr &value1, const ValuePtr &value2);
|
||||
|
||||
/// \brief Joins two types.
|
||||
|
||||
/// \param[in] type1: The first TypePtr to join.
|
||||
/// \param[in] type2: The second TypePtr to join.
|
||||
|
||||
/// \return A TypePtr representing the result of joining type1 and type2.
|
||||
MS_CORE_API TypePtr TypeJoin(const TypePtr &type1, const TypePtr &type2);
|
||||
|
||||
/// \brief Joins two shapes.
|
||||
|
||||
/// \param[in] shape1: The first ShapePtr to join.
|
||||
/// \param[in] shape2: The second ShapePtr to join.
|
||||
|
||||
/// \return A ShapePtr representing the result of joining shape1 and shape2.
|
||||
ShapePtr ShapeJoin(const ShapePtr &shape1, const ShapePtr &shape2);
|
||||
|
||||
/// \brief Joins a list of AbstractBasePtr.
|
||||
|
||||
/// \param[in] args_spec_list: A list of AbstractBasePtr to join.
|
||||
|
||||
/// \return An AbstractBasePtr representing the result of joining the input AbstractBasePtrs.
|
||||
MS_CORE_API AbstractBasePtr AbstractJoin(const AbstractBasePtrList &args_spec_list);
|
||||
|
||||
/// \brief Joins two lists of AbstractBasePtr.
|
||||
|
||||
/// \param[in] spec1: The first list of AbstractBasePtr to join.
|
||||
/// \param[in] spec2: The second list of AbstractBasePtr to join.
|
||||
|
||||
/// \return A list of AbstractBasePtr representing the result of joining spec1 and spec2.
|
||||
MS_CORE_API AbstractBasePtrList AbstractJoin(const AbstractBasePtrList &spec1, const AbstractBasePtrList &spec2);
|
||||
|
||||
// Return an abstract value for the sensitivity of x.
|
||||
// The sensitivity of a function is an Env
|
||||
// The sensitivity of J(x) is x
|
||||
// else self.Clone;
|
||||
/// \brief Transforms the sensitivity of an AbstractBasePtr.
|
||||
|
||||
/// \param[in] spec: The AbstractBasePtr to transform.
|
||||
|
||||
/// \return An AbstractBasePtr representing the transformed AbstractBasePtr.
|
||||
MS_CORE_API AbstractBasePtr SensitivityTransform(const AbstractBasePtr &spec);
|
||||
|
||||
/// \brief Computes the broadcasted shape of two ShapeVectors.
|
||||
|
||||
/// \param[in] shpx: The first ShapeVector.
|
||||
/// \param[in] shpy: The second ShapeVector.
|
||||
|
||||
/// \return A ShapeVector representing the broadcasted shape of shpx and shpy.
|
||||
ShapeVector BroadcastShape(ShapeVector shpx, ShapeVector shpy);
|
||||
|
||||
/// \brief Returns the size of a data type based on its TypeId.
|
||||
|
||||
/// \param[in] data_type: The TypeId of the data type.
|
||||
|
||||
/// \return The size of the data type in bytes.
|
||||
MS_CORE_API size_t TypeIdSize(const TypeId data_type);
|
||||
template <typename T>
|
||||
|
||||
T ShapeSize(const std::vector<T> &shape) {
|
||||
return std::accumulate(shape.begin(), shape.end(), static_cast<T>(1), std::multiplies<T>());
|
||||
}
|
||||
|
||||
// Check dynamic shape routine
|
||||
/// \brief Checks and updates the minimum and maximum shapes based on the given shape.
|
||||
|
||||
/// \param[in] shape: The shape to check.
|
||||
/// \param[in, out] min_shape: A pointer to the minimum shape vector, which will be updated if the input shape is smaller.
|
||||
/// \param[in, out] max_shape: A pointer to the maximum shape vector, which will be updated if the input shape is larger.
|
||||
void CheckMinMaxShape(const ShapeVector &shape, ShapeVector *min_shape, ShapeVector *max_shape);
|
||||
|
||||
/// \brief Creates an AbstractBasePtr from a BaseShapePtr and a TypePtr.
|
||||
|
||||
/// \param[in] base_shape: The BaseShapePtr to use for creating the AbstractBasePtr.
|
||||
/// \param[in] type: The TypePtr to use for creating the AbstractBasePtr.
|
||||
|
||||
/// \return An AbstractBasePtr representing the specified shape and type.
|
||||
AbstractBasePtr MakeAbstract(const BaseShapePtr &base_shape, const TypePtr &type);
|
||||
|
||||
/// \brief Creates an AbstractBasePtr from a MonadTypePtr.
|
||||
|
||||
/// \param[in] type: The MonadTypePtr to use for creating the AbstractBasePtr.
|
||||
|
||||
/// \return An AbstractBasePtr representing the specified monadic type.
|
||||
MS_CORE_API AbstractBasePtr MakeMonadAbstract(const MonadTypePtr &type);
|
||||
|
||||
/// \brief Creates an AbstractBasePtr from a ShapePtr and a TypePtr.
|
||||
|
||||
/// \param[in] shape: The ShapePtr to use for creating the AbstractBasePtr.
|
||||
/// \param[in] type: The TypePtr to use for creating the AbstractBasePtr.
|
||||
|
||||
/// \return An AbstractBasePtr representing the specified shape and type.
|
||||
MS_CORE_API AbstractBasePtr MakeAbstractTensor(const ShapePtr &shape, const TypePtr &type);
|
||||
|
||||
} // namespace abstract
|
||||
} // namespace mindspore
|
||||
#endif // MINDSPORE_CORE_ABSTRACT_UTILS_H_
|
||||
|
|
|
|||
Loading…
Reference in New Issue