Compare commits

..

No commits in common. "master" and "master" have entirely different histories.

11 changed files with 73 additions and 584 deletions

View File

@ -23,124 +23,80 @@ 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>());
}
// 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;
}
bool AbstractFuncAtom::operator==(const AbstractFunction &other) const { return this == &other; }
// Constructor for AbstractFuncUnion with a list of AbstractFuncAtom pointers.
AbstractFuncUnion::AbstractFuncUnion(const AbstractFuncAtomPtrList &func_list) {
func_list_ = func_list;
}
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);
};
// Check if the input AbstractFunctions are not null.
auto build_func_list = [&new_func_list](const AbstractFuncAtomPtr &func) { new_func_list.push_back(func); };
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;
@ -151,90 +107,61 @@ 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());
@ -243,7 +170,6 @@ 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();
@ -251,18 +177,15 @@ 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());
@ -272,7 +195,6 @@ 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_);
@ -282,7 +204,6 @@ 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();
@ -293,17 +214,14 @@ 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());
@ -313,19 +231,16 @@ 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;
}
@ -335,7 +250,6 @@ 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());
@ -343,7 +257,6 @@ 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() << "(";
@ -361,7 +274,6 @@ 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();
@ -371,69 +283,57 @@ 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_);
@ -442,13 +342,11 @@ 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;
}
@ -458,7 +356,6 @@ 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());
@ -466,7 +363,6 @@ 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: {";
@ -487,13 +383,11 @@ 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;
}
@ -506,20 +400,15 @@ 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 {
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_));
auto hash_value = hash_combine(tid(), prim_->hash());
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(args: {";
buffer << "TypedPrimitiveAbstractClosure: primitive: " << prim_->name() << "(args: {";
int64_t i = 0;
for (const auto &arg : args_spec_list_) {
MS_EXCEPTION_IF_NULL(arg);
@ -536,6 +425,5 @@ std::string TypedPrimitiveAbstractClosure::ToString() const {
buffer << "}, output: " << output_->ToString() << ")";
return buffer.str();
}
} // namespace abstract
} // namespace mindspore

View File

@ -38,25 +38,14 @@ 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(); }
};
@ -91,26 +80,14 @@ 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:
@ -136,38 +113,20 @@ 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:

View File

@ -24,13 +24,7 @@
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.
@ -38,14 +32,10 @@ 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 the parent context is not found, raise an exception with detailed information.
if (parent_context == nullptr) {
if (parent_context == nullptr) { // If parent context is not found, we'll raise exception.
std::ostringstream oss;
oss << "BUG: Failed to find parent context in current context: " << this->ToString()
<< ", func_graph: " << func_graph->ToString() << ", parent_graph: ";
@ -62,8 +52,6 @@ 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();
}
@ -71,36 +59,25 @@ 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 the context is still not found, raise an exception with detailed information.
// If this happen, it would be a bug in code. But we raise exception to keep the scene.
if (extant_context == nullptr) {
std::ostringstream oss;
oss << "BUG: Failed to find context for: " << func_graph->ToString() << ", parent_graph: ";
@ -116,55 +93,42 @@ AnalysisContextPtr AnalysisContext::FindOwnOrParentContext(const FuncGraphPtr &f
} else {
oss << " [graph: " << iter.first->ToString();
}
// iter.second cannot be nullptr even if iter.first is nullptr, as it will
// iter.second cannot be nullptr even 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;
@ -173,43 +137,33 @@ 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 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.
// 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.
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);
@ -219,34 +173,23 @@ 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;
// Recursion exit condition for hash().
// hash() recursion exit condition.
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 << "{";
@ -266,7 +209,6 @@ 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;
@ -278,11 +220,6 @@ 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);

View File

@ -47,86 +47,38 @@ class MS_CORE_API AnalysisContext {
}
~AnalysisContext() = default;
/// 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.
// Extend this context with values for another graph.
AnalysisContextPtr NewContext(const FuncGraphPtr &func_graph, const AbstractBasePtrList &args_spec_list);
/// 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.
// Return a context restricted to a graph and 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_;
// A HashMap that records all created context instances for each function graph.
// The extant_context_cache_ is copied from its parent context.
// Record all created context for each func graph.
// `extant_context_cache_` is copied from its parent context.
mindspore::HashMap<FuncGraphPtr, AnalysisContextWeakPtr> extant_context_cache_;
// 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.
// Record all created child contexts from this context.
// Like: key: [func_graph & arguments], value: [child_context]
mindspore::HashMap<FuncGraphPtr, ArgsSpecToAnalysisContextMap> children_cache_;
// 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_.
// There may may be shared_ptr loop like:
// FuncGraphAbstactClosur->AnalysisContext->children_cache_->ArgsSpec->FuncGraphAbstactClosur.
// For break the loop, using all_context_ to clear context_.
static std::list<AnalysisContextPtr> all_context_;
};

View File

@ -25,8 +25,6 @@ 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 << ", ";
@ -52,15 +50,9 @@ std::ostream &operator<<(std::ostream &os, const std::shared_ptr<BaseShape> bs)
return os;
}
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 tid() == other.tid(); }
bool BaseShape::operator!=(const BaseShape &other) const {
// Check if the type identifier of the shapes does not match.
return !(*this == other);
}
bool BaseShape::operator!=(const BaseShape &other) const { return !(*this == other); }
std::string Shape::ToString() const {
std::ostringstream buffer;
@ -82,8 +74,6 @@ 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()) {
@ -109,9 +99,7 @@ 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;
}
@ -120,8 +108,6 @@ 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 << ", ";
@ -136,8 +122,6 @@ 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());
@ -145,7 +129,6 @@ 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

View File

@ -26,7 +26,6 @@
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)
@ -40,7 +39,6 @@ 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>()) {
@ -48,18 +46,15 @@ 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);
@ -71,7 +66,6 @@ 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()) {
@ -87,8 +81,7 @@ TypePtr CheckTensorsDTypeSame(const AbstractTensorPtrList &tensor_list, const Ty
std::ostringstream loginfoBuffer;
loginfoBuffer << "[" << sample_tensor->BuildType()->ToString();
bool error_flag = false;
// Check if the dtypes of all tensors in 'tensor_list' match the dtype of the first tensor.
// Check if other elements have the same type with the first element.
for (size_t index = 1; index < tensor_list.size(); ++index) {
MS_EXCEPTION_IF_NULL(tensor_list[index]);
auto elem = tensor_list[index]->element();
@ -101,13 +94,12 @@ TypePtr CheckTensorsDTypeSame(const AbstractTensorPtrList &tensor_list, const Ty
}
}
if (error_flag) {
MS_EXCEPTION(ValueError) << error_message_prefix << " must be the same, but got " << loginfoBuffer.str() << "]";
MS_EXCEPTION(ValueError) << error_message_prefix << " must be 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) {
@ -121,7 +113,6 @@ 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();
@ -137,7 +128,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()
<< " is not consistent with second arg shape " << shape_base->ToString();
<< " are not consistent with second arg shape " << shape_base->ToString();
}
for (size_t i = 0; i < shape_vector.size(); i++) {
@ -146,12 +137,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()
<< " is not consistent with second arg shape " << shape_base->ToString();
<< " are 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();
@ -165,12 +156,11 @@ 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()
<< " is not consistent with second arg dtype " << type->ToString();
<< " are 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) {
@ -190,8 +180,6 @@ 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) {
@ -204,26 +192,23 @@ 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 a positive integer, but got " << shape[i];
MS_LOG(EXCEPTION) << op << " shape element [" << i << "] must be 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 a positive integer or SHP_ANY, but got "
MS_EXCEPTION(ValueError) << op << " shape element [" << i << "] must be 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) {

View File

@ -30,99 +30,37 @@
namespace mindspore {
namespace abstract {
/// \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.
// check if variable's type is an instance of any of accepts or of a subclass of it.
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);
/// \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);
MS_CORE_API 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>

View File

@ -45,16 +45,9 @@
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();
@ -78,7 +71,6 @@ 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}},
@ -105,11 +97,10 @@ 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;
@ -120,11 +111,7 @@ 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()) {
@ -135,11 +122,9 @@ 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}},
@ -274,12 +259,9 @@ 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}},
@ -332,11 +314,7 @@ 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);
@ -345,10 +323,7 @@ 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;

View File

@ -31,52 +31,33 @@
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_; // 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.
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_;
};
// 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,
@ -87,7 +68,6 @@ 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); \
@ -98,4 +78,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_

View File

@ -24,36 +24,33 @@
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) {
// Initialize min_dims and max_dims with the provided dimensions
// calculate dynamic shape
ShapeVector min_dims(dims.size());
ShapeVector max_dims(dims.size());
MS_EXCEPTION_IF_NULL(shape1);
@ -86,7 +83,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 contain dynamic shape
// both shapes contains 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.";
@ -98,21 +95,18 @@ 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;
}
// If the lengths of the two shapes are not the same, join failed
// lengths of two shapes are not 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;
}
@ -136,41 +130,35 @@ 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 parameter, but the input size is " << args_spec_list.size()
MS_LOG(EXCEPTION) << "AbstractJoin requires at least 1 params, while 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 because the lists do not have the same size. spec1: "
<< ::mindspore::ToString(spec1) << ", spec2: " << ::mindspore::ToString(spec2);
MS_LOG(EXCEPTION) << "Join failed as list don't 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]) {
@ -179,28 +167,20 @@ 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) {
@ -211,7 +191,6 @@ 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().";
}
@ -230,34 +209,26 @@ 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);
@ -283,22 +254,18 @@ 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);
@ -306,12 +273,11 @@ 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 and the type is not TensorType, return an AbstractScalar
// if the size of shape list is empty, return an scalar abstract
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>();
@ -321,7 +287,6 @@ 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>()) {
@ -332,7 +297,6 @@ 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>()) {
@ -340,20 +304,18 @@ 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 a Monad abstract if it is a MonadType
// Return monad abstract if it is monad type.
return MakeMonadAbstract(type->cast<MonadTypePtr>());
} else {
// When sparse is enabled, the "Undetermined" type might be raised and eliminated in optimization passes
// When sparse enabled, the undetermined might be raised and eliminated in opt 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 returned an invalid shape " << base_shape->ToString() << " or type "
<< type->ToString();
MS_LOG(EXCEPTION) << "evaluator return invalid shape " << base_shape->ToString() << "or type. " << type->ToString();
}
}
} // namespace abstract
} // namespace mindspore
} // namespace mindspore

View File

@ -32,102 +32,32 @@
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);
/// \brief Transforms the sensitivity of an AbstractBasePtr.
/// \param[in] spec: The AbstractBasePtr to transform.
/// \return An AbstractBasePtr representing the transformed AbstractBasePtr.
// 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;
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>());
}
/// \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.
// Check dynamic shape routine
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_