forked from huawei/mindspore2022
change sparsetensor to cootensor
This commit is contained in:
parent
a4465947b0
commit
9dfc703f7a
|
|
@ -1,7 +1,7 @@
|
|||
mindspore.SparseTensor
|
||||
======================
|
||||
|
||||
.. py:class:: mindspore.SparseTensor(indices, values, dense_shape)
|
||||
.. py:class:: mindspore.SparseTensor(indices, values, shape)
|
||||
|
||||
用来表示某一张量在给定索引上非零元素的集合。
|
||||
|
||||
|
|
@ -10,14 +10,14 @@ mindspore.SparseTensor
|
|||
.. note::
|
||||
目前不支持PyNative模式。
|
||||
|
||||
对于稠密张量,其 `SparseTensor(indices, values, dense_shape)` 具有 `dense[indices[i]] = values[i]` 。
|
||||
对于稠密张量,其 `SparseTensor(indices, values, shape)` 具有 `dense[indices[i]] = values[i]` 。
|
||||
|
||||
**参数:**
|
||||
|
||||
- **indices** (Tensor) - 形状为 `[N, ndims]` 的二维整数张量,其中N和ndims分别表示稀疏张量中 `values` 的数量和SparseTensor维度的数量。
|
||||
- **values** (Tensor) - 形状为[N]的一维张量,其内部可以为任何数据类型,用来给 `indices` 中的每个元素提供数值。
|
||||
- **dense_shape** (tuple(int)) - 形状为ndims的整数元组,用来指定稀疏矩阵的稠密形状。
|
||||
- **shape** (tuple(int)) - 形状为ndims的整数元组,用来指定稀疏矩阵的稠密形状。
|
||||
|
||||
**返回:**
|
||||
|
||||
SparseTensor,由 `indices` 、 `values` 和 `dense_shape` 组成。
|
||||
SparseTensor,由 `indices` 、 `values` 和 `shape` 组成。
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ typedef enum TypeIdC {
|
|||
kObjectTypeKeyword,
|
||||
kObjectTypeTensorType,
|
||||
kObjectTypeRowTensorType,
|
||||
kObjectTypeSparseTensorType,
|
||||
kObjectTypeCOOTensorType,
|
||||
kObjectTypeUndeterminedType,
|
||||
kObjectTypeClass,
|
||||
kObjectTypeDictionary,
|
||||
|
|
|
|||
|
|
@ -117,6 +117,20 @@ bool SplitCNode(const AnfNodePtr &node, std::vector<AnfNodePtr> *new_inputs) {
|
|||
return true;
|
||||
}
|
||||
|
||||
std::vector<AbstractBasePtr> GetAbstractList(const AnfNodePtr &node, const std::string &prim_name) {
|
||||
MS_EXCEPTION_IF_NULL(node);
|
||||
if (prim_name == prim::kPrimMakeCSRTensor->name()) {
|
||||
auto abs_sparse = dyn_cast<abstract::AbstractCSRTensor>(node->abstract());
|
||||
MS_EXCEPTION_IF_NULL(abs_sparse);
|
||||
return {abs_sparse->indptr(), abs_sparse->indices(), abs_sparse->values(), abs_sparse->dense_shape()};
|
||||
} else if (prim_name == prim::kPrimMakeCOOTensor->name()) {
|
||||
auto abs_sparse = dyn_cast<abstract::AbstractCOOTensor>(node->abstract());
|
||||
MS_EXCEPTION_IF_NULL(abs_sparse);
|
||||
return {abs_sparse->indices(), abs_sparse->values(), abs_sparse->dense_shape()};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
const AnfNodePtr SparseProcess::Process(const FuncGraphPtr &func_graph, const AnfNodePtr &node,
|
||||
const EquivPtr &) const {
|
||||
MS_EXCEPTION_IF_NULL(func_graph);
|
||||
|
|
@ -134,13 +148,9 @@ const AnfNodePtr SparseProcess::Process(const FuncGraphPtr &func_graph, const An
|
|||
if (make_sparse_set.find(prim_name) != make_sparse_set.end()) {
|
||||
std::vector<AnfNodePtr> inputs;
|
||||
inputs.emplace_back(NewValueNode(prim::kPrimMakeTuple));
|
||||
// Inputs of node should be [make_sparse, indices, values, dense_shape], so offset by 1 to get items;
|
||||
(void)inputs.insert(inputs.end(), cnode->inputs().begin() + 1, cnode->inputs().end());
|
||||
auto new_node = cnode->func_graph()->NewCNode(inputs);
|
||||
auto abs_sparse = dyn_cast<abstract::AbstractCSRTensor>(node->abstract());
|
||||
MS_EXCEPTION_IF_NULL(abs_sparse);
|
||||
std::vector<AbstractBasePtr> abstract_list{abs_sparse->indptr(), abs_sparse->indices(), abs_sparse->values(),
|
||||
abs_sparse->dense_shape()};
|
||||
std::vector<AbstractBasePtr> abstract_list = GetAbstractList(node, prim_name);
|
||||
auto abs_res = std::make_shared<abstract::AbstractTuple>(abstract_list);
|
||||
new_node->set_abstract(abs_res);
|
||||
new_node->set_scope(cnode->scope());
|
||||
|
|
|
|||
|
|
@ -159,7 +159,7 @@ std::vector<KernelWithIndex> GetAllOutputWithIndexInner(const AnfNodePtr &node)
|
|||
const PrimitiveSet expand_prims{
|
||||
prim::kPrimMakeTuple,
|
||||
prim::kPrimMakeCSRTensor,
|
||||
prim::kPrimMakeSparseTensor,
|
||||
prim::kPrimMakeCOOTensor,
|
||||
prim::kPrimMakeRowTensor,
|
||||
};
|
||||
// The MakeTuple/MakeSparse node need expand and recurse.
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ void CheckIfValidType(const TypePtr &type) {
|
|||
if (!(type->isa<Number>() || type->isa<TensorType>() || type->isa<Tuple>() || type->isa<TypeType>() ||
|
||||
type->isa<List>() || type->isa<TypeAnything>() || type->isa<RefKeyType>() || type->isa<RefType>() ||
|
||||
type->isa<Function>() || type->isa<TypeNone>() || type->isa<String>() || type->isa<RowTensorType>() ||
|
||||
type->isa<CSRTensorType>() || type->isa<UndeterminedType>() || type->isa<SparseTensorType>() ||
|
||||
type->isa<CSRTensorType>() || type->isa<UndeterminedType>() || type->isa<COOTensorType>() ||
|
||||
type->isa<SymbolicKeyType>() || type->isa<MonadType>())) {
|
||||
MS_LOG(EXCEPTION) << "Unknown type: " << type->type_name();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ typedef enum MsTypeId : unsigned int {
|
|||
kObjectTypeKeyword,
|
||||
kObjectTypeTensorType,
|
||||
kObjectTypeRowTensorType,
|
||||
kObjectTypeSparseTensorType,
|
||||
kObjectTypeCOOTensorType,
|
||||
kObjectTypeUndeterminedType,
|
||||
kObjectTypeClass,
|
||||
kObjectTypeDictionary,
|
||||
|
|
|
|||
|
|
@ -29,12 +29,12 @@ namespace mindspore {
|
|||
namespace opt {
|
||||
using mindspore::abstract::AbstractAttribute;
|
||||
using mindspore::abstract::AbstractClass;
|
||||
using mindspore::abstract::AbstractCOOTensor;
|
||||
using mindspore::abstract::AbstractDictionary;
|
||||
using mindspore::abstract::AbstractJTagged;
|
||||
using mindspore::abstract::AbstractList;
|
||||
using mindspore::abstract::AbstractRowTensor;
|
||||
using mindspore::abstract::AbstractScalar;
|
||||
using mindspore::abstract::AbstractSparseTensor;
|
||||
using mindspore::abstract::AbstractTuple;
|
||||
using mindspore::abstract::AbstractUndetermined;
|
||||
|
||||
|
|
@ -79,8 +79,8 @@ static AbstractBasePtr AdaptAbs(const AbstractBasePtr &t) {
|
|||
return std::make_shared<AbstractTuple>(abs_list->elements());
|
||||
}
|
||||
|
||||
if (t->isa<AbstractSparseTensor>()) {
|
||||
auto abs_sparse = dyn_cast<AbstractSparseTensor>(t);
|
||||
if (t->isa<AbstractCOOTensor>()) {
|
||||
auto abs_sparse = dyn_cast<AbstractCOOTensor>(t);
|
||||
std::vector<AbstractBasePtr> abstract_list{abs_sparse->indices(), abs_sparse->values(), abs_sparse->dense_shape()};
|
||||
return std::make_shared<AbstractTuple>(abstract_list);
|
||||
}
|
||||
|
|
@ -511,19 +511,15 @@ bool CleanAfterOptA(const FuncGraphPtr &root, const FuncGraphManagerPtr &manager
|
|||
new_node = ConvertListSetItemToTupleSetItem(cnode);
|
||||
} else if (IsValueNode<ValueList>(node)) {
|
||||
new_node = ConvertValueListNodeToValueTupleNode(node->cast<ValueNodePtr>());
|
||||
} else if (IsPrimitiveCNode(node, prim::kPrimMakeSparseTensor) ||
|
||||
IsPrimitiveCNode(node, prim::kPrimMakeRowTensor)) {
|
||||
} else if (IsPrimitiveCNode(node, prim::kPrimMakeRowTensor)) {
|
||||
new_node = ConvertMakeSparseToMakeTuple(cnode);
|
||||
} else if (IsPrimitiveCNode(node, prim::kPrimSparseTensorGetIndices) ||
|
||||
IsPrimitiveCNode(node, prim::kPrimRowTensorGetIndices)) {
|
||||
} else if (IsPrimitiveCNode(node, prim::kPrimRowTensorGetIndices)) {
|
||||
constexpr int64_t indices_index = 0;
|
||||
new_node = ConvertSparseGetAttrToTupleGetItem(cnode, indices_index);
|
||||
} else if (IsPrimitiveCNode(node, prim::kPrimSparseTensorGetValues) ||
|
||||
IsPrimitiveCNode(node, prim::kPrimRowTensorGetValues)) {
|
||||
} else if (IsPrimitiveCNode(node, prim::kPrimRowTensorGetValues)) {
|
||||
constexpr int64_t value_index = 1;
|
||||
new_node = ConvertSparseGetAttrToTupleGetItem(cnode, value_index);
|
||||
} else if (IsPrimitiveCNode(node, prim::kPrimSparseTensorGetDenseShape) ||
|
||||
IsPrimitiveCNode(node, prim::kPrimRowTensorGetDenseShape)) {
|
||||
} else if (IsPrimitiveCNode(node, prim::kPrimRowTensorGetDenseShape)) {
|
||||
constexpr int64_t shape_index = 2;
|
||||
new_node = ConvertSparseGetAttrToTupleGetItem(cnode, shape_index);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -249,7 +249,7 @@ OptimizeIRPassLib::OptimizeIRPassLib() {
|
|||
// SparseTensor Eliminate
|
||||
sparse_tensor_eliminate_ = MakeSubstitution(
|
||||
std::make_shared<SparseTensorEliminater>(), "sparse_tensor_eliminate",
|
||||
{prim::kPrimSparseTensorGetIndices, prim::kPrimSparseTensorGetValues, prim::kPrimSparseTensorGetDenseShape});
|
||||
{prim::kPrimCOOTensorGetIndices, prim::kPrimCOOTensorGetValues, prim::kPrimCOOTensorGetDenseShape});
|
||||
|
||||
// Value_Based Eliminate
|
||||
value_based_eliminate_ = MakeSubstitution(std::make_shared<ValueBasedEliminate>(), "value_based_eliminate",
|
||||
|
|
|
|||
|
|
@ -35,10 +35,10 @@ class SparseTensorEliminater : public OptimizerCaller {
|
|||
public:
|
||||
AnfNodePtr operator()(const OptimizerPtr &, const AnfNodePtr &node) override {
|
||||
PatternNode x, y, z;
|
||||
auto sparse = PPrimitive(prim::kPrimMakeSparseTensor, x, y, z).MinExtraNodes(0);
|
||||
MATCH_REPLACE(node, PPrimitive(prim::kPrimSparseTensorGetIndices, sparse), x);
|
||||
MATCH_REPLACE(node, PPrimitive(prim::kPrimSparseTensorGetValues, sparse), y);
|
||||
MATCH_REPLACE(node, PPrimitive(prim::kPrimSparseTensorGetDenseShape, sparse), z);
|
||||
auto sparse = PPrimitive(prim::kPrimMakeCOOTensor, x, y, z).MinExtraNodes(0);
|
||||
MATCH_REPLACE(node, PPrimitive(prim::kPrimCOOTensorGetIndices, sparse), x);
|
||||
MATCH_REPLACE(node, PPrimitive(prim::kPrimCOOTensorGetValues, sparse), y);
|
||||
MATCH_REPLACE(node, PPrimitive(prim::kPrimCOOTensorGetDenseShape, sparse), z);
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -239,11 +239,11 @@ BuiltInTypeMap &GetAttrMap() {
|
|||
{"indices", prim::kPrimRowTensorGetIndices}, // F.row_tensor_get_indices
|
||||
{"dense_shape", prim::kPrimRowTensorGetDenseShape}, // F.row_tensor_get_dense_shape
|
||||
}},
|
||||
{kObjectTypeSparseTensorType,
|
||||
{kObjectTypeCOOTensorType,
|
||||
{
|
||||
{"values", prim::kPrimSparseTensorGetValues}, // F.sparse_tensor_get_values
|
||||
{"indices", prim::kPrimSparseTensorGetIndices}, // F.sparse_tensor_get_indices
|
||||
{"dense_shape", prim::kPrimSparseTensorGetDenseShape}, // F.sparse_tensor_get_dense_shape
|
||||
{"values", prim::kPrimCOOTensorGetValues}, // F.coo_tensor_get_values
|
||||
{"indices", prim::kPrimCOOTensorGetIndices}, // F.coo_tensor_get_indices
|
||||
{"shape", prim::kPrimCOOTensorGetDenseShape}, // F.coo_tensor_get_dense_shape
|
||||
}},
|
||||
{kObjectTypeCSRTensorType,
|
||||
{
|
||||
|
|
|
|||
|
|
@ -557,8 +557,8 @@ py::dict ConvertAbstractToPython(const AbstractBasePtr &abs_base, bool only_conv
|
|||
dic[ATTR_SHAPE] = arg->shape()->shape();
|
||||
dic[ATTR_DTYPE] = arg->BuildType();
|
||||
dic[ATTR_VALUE] = BuildValue(arg->BuildValue());
|
||||
} else if (abs_base->isa<AbstractSparseTensor>()) {
|
||||
auto arg = dyn_cast<AbstractSparseTensor>(abs_base);
|
||||
} else if (abs_base->isa<AbstractCOOTensor>()) {
|
||||
auto arg = dyn_cast<AbstractCOOTensor>(abs_base);
|
||||
dic[ATTR_SHAPE] = arg->shape()->shape();
|
||||
dic[ATTR_DTYPE] = arg->BuildType();
|
||||
dic[ATTR_VALUE] = BuildValue(arg->BuildValue());
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ namespace mindspore {
|
|||
namespace validator {
|
||||
using mindspore::abstract::AbstractBase;
|
||||
using mindspore::abstract::AbstractClass;
|
||||
using mindspore::abstract::AbstractCOOTensor;
|
||||
using mindspore::abstract::AbstractCSRTensor;
|
||||
using mindspore::abstract::AbstractError;
|
||||
using mindspore::abstract::AbstractFunction;
|
||||
|
|
@ -39,7 +40,6 @@ using mindspore::abstract::AbstractList;
|
|||
using mindspore::abstract::AbstractRef;
|
||||
using mindspore::abstract::AbstractRowTensor;
|
||||
using mindspore::abstract::AbstractScalar;
|
||||
using mindspore::abstract::AbstractSparseTensor;
|
||||
using mindspore::abstract::AbstractTensor;
|
||||
using mindspore::abstract::AbstractTuple;
|
||||
using mindspore::abstract::AbstractType;
|
||||
|
|
@ -122,7 +122,7 @@ void ValidateAbstract(const AnfNodePtr &node) {
|
|||
bool is_legal_abstract = abstract->isa<AbstractType>() || abstract->isa<AbstractFunction>() ||
|
||||
abstract->isa<AbstractTuple>() || abstract->isa<AbstractList>() ||
|
||||
abstract->isa<AbstractTensor>() || abstract->isa<AbstractRowTensor>() ||
|
||||
abstract->isa<AbstractSparseTensor>() || abstract->isa<AbstractCSRTensor>() ||
|
||||
abstract->isa<AbstractCOOTensor>() || abstract->isa<AbstractCSRTensor>() ||
|
||||
abstract->isa<abstract::AbstractRefKey>() || abstract->isa<AbstractRef>() ||
|
||||
abstract->isa<abstract::AbstractNone>() || abstract->isa<abstract::AbstractMonad>();
|
||||
if (is_legal_abstract) {
|
||||
|
|
|
|||
|
|
@ -154,9 +154,9 @@ REGISTER_PYBIND_DEFINE(
|
|||
(void)py::class_<RowTensorType, Type, std::shared_ptr<RowTensorType>>(m_sub, "RowTensorType")
|
||||
.def(py::init())
|
||||
.def_property_readonly("ElementType", &RowTensorType::element, "Get the RowTensorType's element type.");
|
||||
(void)py::class_<SparseTensorType, Type, std::shared_ptr<SparseTensorType>>(m_sub, "SparseTensorType")
|
||||
(void)py::class_<COOTensorType, Type, std::shared_ptr<COOTensorType>>(m_sub, "COOTensorType")
|
||||
.def(py::init())
|
||||
.def_property_readonly("ElementType", &SparseTensorType::element, "Get the SparseTensorType's element type.");
|
||||
.def_property_readonly("ElementType", &COOTensorType::element, "Get the COOTensorType's element type.");
|
||||
(void)py::class_<CSRTensorType, Type, std::shared_ptr<CSRTensorType>>(m_sub, "CSRTensorType")
|
||||
.def(py::init())
|
||||
.def_property_readonly("ElementType", &CSRTensorType::element, "Get the CSRTensorType's element type.");
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
#include "pybind_api/ir/tensor_py.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "pybind_api/api_register.h"
|
||||
#include "abstract/abstract_value.h"
|
||||
#include "utils/shape_utils.h"
|
||||
|
|
@ -23,6 +25,11 @@
|
|||
|
||||
namespace mindspore {
|
||||
namespace tensor {
|
||||
constexpr ssize_t kPyBufItemSize1 = 1;
|
||||
constexpr ssize_t kPyBufItemSize2 = 2;
|
||||
constexpr ssize_t kPyBufItemSize4 = 4;
|
||||
constexpr ssize_t kPyBufItemSize8 = 8;
|
||||
|
||||
static TypeId GetDataType(const py::buffer_info &buf) {
|
||||
if (buf.format.size() == 1) {
|
||||
switch (buf.format.front()) {
|
||||
|
|
@ -30,11 +37,11 @@ static TypeId GetDataType(const py::buffer_info &buf) {
|
|||
case 'f':
|
||||
case 'd':
|
||||
switch (buf.itemsize) {
|
||||
case 2:
|
||||
case kPyBufItemSize2:
|
||||
return TypeId::kNumberTypeFloat16;
|
||||
case 4:
|
||||
case kPyBufItemSize4:
|
||||
return TypeId::kNumberTypeFloat32;
|
||||
case 8:
|
||||
case kPyBufItemSize8:
|
||||
return TypeId::kNumberTypeFloat64;
|
||||
}
|
||||
break;
|
||||
|
|
@ -44,13 +51,13 @@ static TypeId GetDataType(const py::buffer_info &buf) {
|
|||
case 'l':
|
||||
case 'q':
|
||||
switch (buf.itemsize) {
|
||||
case 1:
|
||||
case kPyBufItemSize1:
|
||||
return TypeId::kNumberTypeInt8;
|
||||
case 2:
|
||||
case kPyBufItemSize2:
|
||||
return TypeId::kNumberTypeInt16;
|
||||
case 4:
|
||||
case kPyBufItemSize4:
|
||||
return TypeId::kNumberTypeInt32;
|
||||
case 8:
|
||||
case kPyBufItemSize8:
|
||||
return TypeId::kNumberTypeInt64;
|
||||
}
|
||||
break;
|
||||
|
|
@ -60,13 +67,13 @@ static TypeId GetDataType(const py::buffer_info &buf) {
|
|||
case 'L':
|
||||
case 'Q':
|
||||
switch (buf.itemsize) {
|
||||
case 1:
|
||||
case kPyBufItemSize1:
|
||||
return TypeId::kNumberTypeUInt8;
|
||||
case 2:
|
||||
case kPyBufItemSize2:
|
||||
return TypeId::kNumberTypeUInt16;
|
||||
case 4:
|
||||
case kPyBufItemSize4:
|
||||
return TypeId::kNumberTypeUInt32;
|
||||
case 8:
|
||||
case kPyBufItemSize8:
|
||||
return TypeId::kNumberTypeUInt64;
|
||||
}
|
||||
break;
|
||||
|
|
@ -665,5 +672,34 @@ REGISTER_PYBIND_DEFINE(
|
|||
.def("__str__", &CSRTensor::ToString)
|
||||
.def("__repr__", &CSRTensor::ToString);
|
||||
}));
|
||||
|
||||
py::tuple COOTensorPy::GetPyTupleShape(const COOTensor &coo_tensor) {
|
||||
auto &shape = coo_tensor.shape();
|
||||
py::tuple dims(shape.size());
|
||||
for (size_t i = 0; i < dims.size(); ++i) {
|
||||
dims[i] = py::int_(shape[i]);
|
||||
}
|
||||
return dims;
|
||||
}
|
||||
|
||||
REGISTER_PYBIND_DEFINE(COOTensor, ([](const py::module *m) {
|
||||
// Define python COOTensor class.
|
||||
(void)py::class_<COOTensor, std::shared_ptr<COOTensor>>(*m, "COOTensor")
|
||||
.def(py::init([](const Tensor &indices, const Tensor &values, const py::tuple &shape) {
|
||||
return std::make_shared<COOTensor>(std::make_shared<Tensor>(indices),
|
||||
std::make_shared<Tensor>(values),
|
||||
GetShapeFromTuple(shape));
|
||||
}),
|
||||
py::arg("indices"), py::arg("values"), py::arg("shape"))
|
||||
.def(py::init(
|
||||
[](const COOTensor &coo_tensor) { return std::make_shared<COOTensor>(coo_tensor); }),
|
||||
py::arg("input"))
|
||||
.def_property_readonly("_shape", COOTensorPy::GetPyTupleShape)
|
||||
.def_property_readonly("_dtype", &COOTensor::Dtype)
|
||||
.def_property_readonly("_indices", &COOTensor::GetIndices)
|
||||
.def_property_readonly("_values", &COOTensor::GetValues)
|
||||
.def("__str__", &COOTensor::ToString)
|
||||
.def("__repr__", &COOTensor::ToString);
|
||||
}));
|
||||
} // namespace tensor
|
||||
} // namespace mindspore
|
||||
|
|
|
|||
|
|
@ -124,6 +124,12 @@ class CSRTensorPy {
|
|||
public:
|
||||
static py::tuple GetPyTupleShape(const CSRTensor &csr_tensor);
|
||||
};
|
||||
|
||||
// COOTensor python wrapper and adapter class.
|
||||
class COOTensorPy {
|
||||
public:
|
||||
static py::tuple GetPyTupleShape(const COOTensor &coo_tensor);
|
||||
};
|
||||
} // namespace tensor
|
||||
} // namespace mindspore
|
||||
|
||||
|
|
|
|||
|
|
@ -83,18 +83,20 @@ size_t CountValueNum(const ValueTuplePtr &value_tuple);
|
|||
// sparse_attr_map converts CNode{kPrimSparseGetAttr, SparseTensor}
|
||||
// to CNode{kPrimTupleGetItem, SparseTensor, int64_t(index)}, used
|
||||
// in backend common optimization pass: sparse_process.cc
|
||||
const mindspore::HashMap<std::string, int64_t> sparse_attr_map = {{prim::kPrimCSRTensorGetIndptr->name(), 0},
|
||||
{prim::kPrimCSRTensorGetIndices->name(), 1},
|
||||
{prim::kPrimCSRTensorGetValues->name(), 2},
|
||||
{prim::kPrimCSRTensorGetDenseShape->name(), 3}};
|
||||
const mindspore::HashMap<std::string, int64_t> sparse_attr_map = {
|
||||
{prim::kPrimCSRTensorGetIndptr->name(), 0}, {prim::kPrimCSRTensorGetIndices->name(), 1},
|
||||
{prim::kPrimCSRTensorGetValues->name(), 2}, {prim::kPrimCSRTensorGetDenseShape->name(), 3},
|
||||
{prim::kPrimCOOTensorGetIndices->name(), 0}, {prim::kPrimCOOTensorGetValues->name(), 1},
|
||||
{prim::kPrimCOOTensorGetDenseShape->name(), 2}};
|
||||
// make_sparse_set records all make_sparse primitives, and tries to replace
|
||||
// make_sparse to make_tuple, used in backend common optimization pass:
|
||||
// sparse_process.cc
|
||||
const mindspore::HashSet<std::string> make_sparse_set = {{prim::kPrimMakeCSRTensor->name()}};
|
||||
const mindspore::HashSet<std::string> make_sparse_set = {{prim::kPrimMakeCSRTensor->name()},
|
||||
{prim::kPrimMakeCOOTensor->name()}};
|
||||
// sparse_op_set records all sparse_compute operators, which takes sparsetensor
|
||||
// and (possibly) dense tensors, used in backend common optimization pass:
|
||||
// sparse_process.cc
|
||||
const mindspore::HashSet<std::string> sparse_op_set = {{prim::kPrimSparseTensorDenseMatmul->name()},
|
||||
const mindspore::HashSet<std::string> sparse_op_set = {{prim::kPrimCOOTensorDenseMatmul->name()},
|
||||
{prim::kPrimCSRDenseMul->name()},
|
||||
{prim::kPrimCSRReduceSum->name()},
|
||||
{prim::kPrimCSRMV->name()},
|
||||
|
|
|
|||
|
|
@ -47,6 +47,8 @@ py::object VectorRefToPyData(const VectorRef &value_list);
|
|||
py::object VectorRefToPyData(const VectorRef &value_list, const AbstractBasePtr &output);
|
||||
// Wrap VectorRef to CSRTensor
|
||||
py::object MakeCSRTensor(const VectorRef &value_list);
|
||||
py::object MakeCOOTensor(const VectorRef &value_list);
|
||||
ShapeVector ConvertToShapeVector(const ValuePtr &shape_ptr, const VectorRef &value_list, size_t shape_idx);
|
||||
py::object CSRTensorToPyData(const tensor::CSRTensorPtr &csr_tensor) {
|
||||
auto ref = py::tuple(1);
|
||||
ref[0] = csr_tensor;
|
||||
|
|
@ -295,7 +297,7 @@ py::object AnyToPyData(const Any &value) {
|
|||
|
||||
py::object BaseRefToPyData(const BaseRef &value, const AbstractBasePtr &output) {
|
||||
py::object ret;
|
||||
// If output value is a tuple, check if abstract is a SparseTensor in funcgraph output
|
||||
// If output value is a tuple, check if abstract is a COOTensor in funcgraph output
|
||||
if (utils::isa<VectorRef>(value)) {
|
||||
MS_LOG(DEBUG) << "BaseRefToPyData, value is tuple: " << value.ToString();
|
||||
auto vec_ref = utils::cast<VectorRef>(value);
|
||||
|
|
@ -415,10 +417,13 @@ py::object VectorRefToPyData(const VectorRef &value_list) {
|
|||
|
||||
py::object VectorRefToPyData(const VectorRef &value_list, const AbstractBasePtr &output) {
|
||||
MS_LOG(DEBUG) << "vector_ref";
|
||||
// Current VectorRef reflects a SparseTensor type
|
||||
// Current VectorRef reflects a COOTensor type
|
||||
if (output->isa<abstract::AbstractCSRTensor>()) {
|
||||
return MakeCSRTensor(value_list);
|
||||
}
|
||||
if (output->isa<abstract::AbstractCOOTensor>()) {
|
||||
return MakeCOOTensor(value_list);
|
||||
}
|
||||
py::object ret;
|
||||
size_t value_size = value_list.size();
|
||||
auto ref_tuple = py::tuple(value_size);
|
||||
|
|
@ -626,20 +631,10 @@ bool IsGraphOutputValueNodeOrParameter(const AnfNodePtr &output, const py::tuple
|
|||
return false;
|
||||
}
|
||||
|
||||
py::object MakeCSRTensor(const VectorRef &value_list) {
|
||||
constexpr size_t kCSRTensorInputSize{4};
|
||||
if (value_list.size() != kCSRTensorInputSize) {
|
||||
MS_LOG(EXCEPTION) << "CSRTensor must have 4 inputs.";
|
||||
}
|
||||
using TensorPtr = tensor::TensorPtr;
|
||||
using CSRTensor = tensor::CSRTensor;
|
||||
TensorPtr indptr = utils::cast<TensorPtr>(value_list[0]);
|
||||
TensorPtr indices = utils::cast<TensorPtr>(value_list[1]);
|
||||
TensorPtr values = utils::cast<TensorPtr>(value_list[2]);
|
||||
ValuePtr shape_ptr = utils::cast<ValuePtr>(value_list[3]);
|
||||
ShapeVector ConvertToShapeVector(const ValuePtr &shape_ptr, const VectorRef &value_list, size_t shape_idx) {
|
||||
MS_EXCEPTION_IF_NULL(shape_ptr);
|
||||
ShapeVector shape;
|
||||
ValueTuplePtr shape_tuple = shape_ptr->cast<ValueTuplePtr>();
|
||||
ShapeVector shape{};
|
||||
// CSRTensor shape is a tuple on GPU and CPU
|
||||
if (shape_tuple) {
|
||||
for (const auto &v : shape_tuple->value()) {
|
||||
MS_EXCEPTION_IF_NULL(v);
|
||||
|
|
@ -647,22 +642,59 @@ py::object MakeCSRTensor(const VectorRef &value_list) {
|
|||
MS_EXCEPTION_IF_NULL(scalar);
|
||||
shape.push_back(GetValue<int64_t>(scalar));
|
||||
}
|
||||
// CSRTensor shape is a VectorRef(TensorPtr, TensorPtr) on Ascend
|
||||
} else {
|
||||
auto shape_ref = utils::cast<VectorRef>(value_list[3]);
|
||||
auto shape_ref = utils::cast<VectorRef>(value_list[shape_idx]);
|
||||
MS_EXCEPTION_IF_NULL(shape_ref);
|
||||
for (const auto &v : shape_ref) {
|
||||
MS_EXCEPTION_IF_NULL(v);
|
||||
auto tensorptr = utils::cast<TensorPtr>(v);
|
||||
auto tensorptr = utils::cast<tensor::TensorPtr>(v);
|
||||
MS_EXCEPTION_IF_NULL(tensorptr);
|
||||
if (tensorptr->DataDim() != 0) {
|
||||
MS_LOG(EXCEPTION) << "Element in CSRTensor's shape must be scalar!";
|
||||
MS_LOG(EXCEPTION) << "Element in COOTensor's shape must be scalar!";
|
||||
}
|
||||
tensorptr->data_sync(false);
|
||||
shape.push_back(*(static_cast<int64_t *>(tensorptr->data_c())));
|
||||
}
|
||||
}
|
||||
return shape;
|
||||
}
|
||||
|
||||
py::object MakeCSRTensor(const VectorRef &value_list) {
|
||||
constexpr size_t kCSRTensorInputSize{4};
|
||||
if (value_list.size() != kCSRTensorInputSize) {
|
||||
MS_LOG(EXCEPTION) << "CSRTensor must have 4 inputs.";
|
||||
}
|
||||
using TensorPtr = tensor::TensorPtr;
|
||||
using CSRTensor = tensor::CSRTensor;
|
||||
constexpr size_t kIndptrIdx{0};
|
||||
constexpr size_t kIndicesIdx{1};
|
||||
constexpr size_t kValuesIdx{2};
|
||||
constexpr size_t kShapeIdx{3};
|
||||
TensorPtr indptr = utils::cast<TensorPtr>(value_list[kIndptrIdx]);
|
||||
TensorPtr indices = utils::cast<TensorPtr>(value_list[kIndicesIdx]);
|
||||
TensorPtr values = utils::cast<TensorPtr>(value_list[kValuesIdx]);
|
||||
ValuePtr shape_ptr = utils::cast<ValuePtr>(value_list[kShapeIdx]);
|
||||
|
||||
ShapeVector shape = ConvertToShapeVector(shape_ptr, value_list, kShapeIdx);
|
||||
auto csr_tensor_ptr = std::make_shared<CSRTensor>(indptr, indices, values, shape);
|
||||
return CSRTensorToPyData(csr_tensor_ptr);
|
||||
}
|
||||
|
||||
py::object MakeCOOTensor(const VectorRef &value_list) {
|
||||
constexpr size_t kCOOTensorInputSize{3};
|
||||
constexpr size_t kIndicesIdx{0};
|
||||
constexpr size_t kValuesIdx{1};
|
||||
constexpr size_t kShapeIdx{2};
|
||||
if (value_list.size() != kCOOTensorInputSize) {
|
||||
MS_LOG(EXCEPTION) << "COOTensor must have " << kCOOTensorInputSize << "inputs.";
|
||||
}
|
||||
tensor::TensorPtr indices = utils::cast<tensor::TensorPtr>(value_list[kIndicesIdx]);
|
||||
tensor::TensorPtr values = utils::cast<tensor::TensorPtr>(value_list[kValuesIdx]);
|
||||
ValuePtr shape_ptr = utils::cast<ValuePtr>(value_list[kShapeIdx]);
|
||||
|
||||
ShapeVector shape = ConvertToShapeVector(shape_ptr, value_list, kShapeIdx);
|
||||
auto ref = py::tuple(1);
|
||||
auto coo_tensor_ptr = std::make_shared<tensor::COOTensor>(indices, values, shape);
|
||||
ref[0] = coo_tensor_ptr;
|
||||
return ref[0];
|
||||
}
|
||||
} // namespace mindspore
|
||||
|
|
|
|||
|
|
@ -1017,7 +1017,7 @@ void MindRTBackend::ConstructOutputs(const AnfNodePtr &output_node,
|
|||
const PrimitiveSet expand_prims{
|
||||
prim::kPrimMakeTuple,
|
||||
prim::kPrimMakeCSRTensor,
|
||||
prim::kPrimMakeSparseTensor,
|
||||
prim::kPrimMakeCOOTensor,
|
||||
prim::kPrimMakeRowTensor,
|
||||
};
|
||||
// The MakeTuple/MakeSaprse node need expand and recurse.
|
||||
|
|
|
|||
|
|
@ -1461,16 +1461,16 @@ std::string AbstractRowTensor::ToString() const {
|
|||
return buffer.str();
|
||||
}
|
||||
|
||||
// SparseTensor
|
||||
TypePtr AbstractSparseTensor::BuildType() const {
|
||||
// COOTensor
|
||||
TypePtr AbstractCOOTensor::BuildType() const {
|
||||
MS_EXCEPTION_IF_NULL(element());
|
||||
TypePtr element_type = element()->BuildType();
|
||||
return std::make_shared<SparseTensorType>(element_type);
|
||||
return std::make_shared<COOTensorType>(element_type);
|
||||
}
|
||||
|
||||
AbstractBasePtr AbstractSparseTensor::Clone() const {
|
||||
AbstractBasePtr AbstractCOOTensor::Clone() const {
|
||||
MS_EXCEPTION_IF_NULL(element());
|
||||
auto clone = std::make_shared<AbstractSparseTensor>(element()->Clone());
|
||||
auto clone = std::make_shared<AbstractCOOTensor>(element()->Clone());
|
||||
ShapePtr shp = shape();
|
||||
MS_EXCEPTION_IF_NULL(shp);
|
||||
clone->set_shape(shp->Clone());
|
||||
|
|
@ -1490,9 +1490,9 @@ AbstractBasePtr AbstractSparseTensor::Clone() const {
|
|||
return clone;
|
||||
}
|
||||
|
||||
AbstractBasePtr AbstractSparseTensor::Broaden() const {
|
||||
AbstractBasePtr AbstractCOOTensor::Broaden() const {
|
||||
MS_EXCEPTION_IF_NULL(element());
|
||||
auto broaden = std::make_shared<AbstractSparseTensor>(element()->Broaden());
|
||||
auto broaden = std::make_shared<AbstractCOOTensor>(element()->Broaden());
|
||||
auto shp = shape();
|
||||
MS_EXCEPTION_IF_NULL(shp);
|
||||
MS_EXCEPTION_IF_NULL(indices_);
|
||||
|
|
@ -1512,9 +1512,9 @@ AbstractBasePtr AbstractSparseTensor::Broaden() const {
|
|||
return broaden;
|
||||
}
|
||||
|
||||
AbstractBasePtr AbstractSparseTensor::BroadenWithShape() const {
|
||||
AbstractBasePtr AbstractCOOTensor::BroadenWithShape() const {
|
||||
MS_EXCEPTION_IF_NULL(element());
|
||||
auto broaden = std::make_shared<AbstractSparseTensor>(element()->Broaden());
|
||||
auto broaden = std::make_shared<AbstractCOOTensor>(element()->Broaden());
|
||||
auto this_shape = shape();
|
||||
MS_EXCEPTION_IF_NULL(this_shape);
|
||||
auto shp = this_shape->Clone();
|
||||
|
|
@ -1537,7 +1537,7 @@ AbstractBasePtr AbstractSparseTensor::BroadenWithShape() const {
|
|||
return broaden;
|
||||
}
|
||||
|
||||
std::string AbstractSparseTensor::ToString() const {
|
||||
std::string AbstractCOOTensor::ToString() const {
|
||||
std::ostringstream buffer;
|
||||
BaseShapePtr shape_track = GetShapeTrack();
|
||||
MS_EXCEPTION_IF_NULL(shape_track);
|
||||
|
|
|
|||
|
|
@ -1482,28 +1482,28 @@ class MS_CORE_API AbstractRowTensor final : public AbstractUndetermined {
|
|||
AbstractTuplePtr dense_shape_;
|
||||
};
|
||||
|
||||
/// \brief Class AbstractSparseTensor describes a SparseTensor's abstract value.
|
||||
class MS_CORE_API AbstractSparseTensor final : public AbstractUndetermined {
|
||||
/// \brief Class AbstractCOOTensor describes a COOTensor's abstract value.
|
||||
class MS_CORE_API AbstractCOOTensor final : public AbstractUndetermined {
|
||||
public:
|
||||
/// \brief Constructor of AbstractSparseTensor.
|
||||
/// \brief Constructor of AbstractCOOTensor.
|
||||
///
|
||||
/// \param[in] element The abstract which is wrapped to be the abstract value of SparseTensor.
|
||||
/// \param[in] element The abstract which is wrapped to be the abstract value of COOTensor.
|
||||
/// \param[in] shape The dimension of the abstract.
|
||||
explicit AbstractSparseTensor(const AbstractBasePtr &element, const BaseShapePtr &shape = std::make_shared<Shape>())
|
||||
explicit AbstractCOOTensor(const AbstractBasePtr &element, const BaseShapePtr &shape = std::make_shared<Shape>())
|
||||
: AbstractUndetermined(element, shape) {}
|
||||
|
||||
/// \brief Constructor of AbstractSparseTensor.
|
||||
/// \brief Constructor of AbstractCOOTensor.
|
||||
///
|
||||
/// \param[in] element_type The type of SparseTensor.
|
||||
/// \param[in] shape The dimension of SparseTensor.
|
||||
AbstractSparseTensor(const TypePtr &element_type, const ShapeVector &shape)
|
||||
/// \param[in] element_type The type of COOTensor.
|
||||
/// \param[in] shape The dimension of COOTensor.
|
||||
AbstractCOOTensor(const TypePtr &element_type, const ShapeVector &shape)
|
||||
: AbstractUndetermined(element_type, shape) {}
|
||||
|
||||
/// \brief Destructor of AbstractSparseTensor.
|
||||
~AbstractSparseTensor() override = default;
|
||||
MS_DECLARE_PARENT(AbstractSparseTensor, AbstractUndetermined)
|
||||
/// \brief Destructor of AbstractCOOTensor.
|
||||
~AbstractCOOTensor() override = default;
|
||||
MS_DECLARE_PARENT(AbstractCOOTensor, AbstractUndetermined)
|
||||
|
||||
/// \brief Get the indices of SparseTensor.
|
||||
/// \brief Get the indices of COOTensor.
|
||||
///
|
||||
/// \return A pointer to the abstract tensor.
|
||||
const AbstractTensorPtr indices() const { return indices_; }
|
||||
|
|
@ -1520,7 +1520,7 @@ class MS_CORE_API AbstractSparseTensor final : public AbstractUndetermined {
|
|||
|
||||
/// \brief Set the values.
|
||||
///
|
||||
/// \param[in] values The values of SparseTensor.
|
||||
/// \param[in] values The values of COOTensor.
|
||||
void set_values(const AbstractTensorPtr &values) { values_ = values; }
|
||||
|
||||
/// \brief Get the dense shape.
|
||||
|
|
@ -1530,7 +1530,7 @@ class MS_CORE_API AbstractSparseTensor final : public AbstractUndetermined {
|
|||
|
||||
/// \brief Set the dense shape.
|
||||
///
|
||||
/// \param[in] dense_shape The dense shape of SparseTensor.
|
||||
/// \param[in] dense_shape The dense shape of COOTensor.
|
||||
void set_dense_shape(const AbstractTuplePtr &dense_shape) { dense_shape_ = dense_shape; }
|
||||
|
||||
TypePtr BuildType() const override;
|
||||
|
|
|
|||
|
|
@ -149,14 +149,14 @@ AbstractBasePtr InferImplDebug(const AnalysisEnginePtr &, const PrimitivePtr &pr
|
|||
const AbstractBasePtrList &args_spec_list);
|
||||
template <typename T>
|
||||
std::shared_ptr<T> InferSparseAttr(const PrimitivePtr &primitive, const AbstractBasePtrList &args_spec_list);
|
||||
AbstractBasePtr InferImplMakeSparseTensor(const AnalysisEnginePtr &, const PrimitivePtr &primitive,
|
||||
const AbstractBasePtrList &args_spec_list);
|
||||
AbstractBasePtr InferImplSparseTensorGetValues(const AnalysisEnginePtr &, const PrimitivePtr &primitive,
|
||||
const AbstractBasePtrList &args_spec_list);
|
||||
AbstractBasePtr InferImplSparseTensorGetIndices(const AnalysisEnginePtr &, const PrimitivePtr &primitive,
|
||||
AbstractBasePtr InferImplMakeCOOTensor(const AnalysisEnginePtr &, const PrimitivePtr &primitive,
|
||||
const AbstractBasePtrList &args_spec_list);
|
||||
AbstractBasePtr InferImplCOOTensorGetValues(const AnalysisEnginePtr &, const PrimitivePtr &primitive,
|
||||
const AbstractBasePtrList &args_spec_list);
|
||||
AbstractBasePtr InferImplCOOTensorGetIndices(const AnalysisEnginePtr &, const PrimitivePtr &primitive,
|
||||
const AbstractBasePtrList &args_spec_list);
|
||||
AbstractBasePtr InferImplCOOTensorGetDenseShape(const AnalysisEnginePtr &, const PrimitivePtr &primitive,
|
||||
const AbstractBasePtrList &args_spec_list);
|
||||
AbstractBasePtr InferImplSparseTensorGetDenseShape(const AnalysisEnginePtr &, const PrimitivePtr &primitive,
|
||||
const AbstractBasePtrList &args_spec_list);
|
||||
AbstractBasePtr InferImplCSRMul(const AnalysisEnginePtr &, const PrimitivePtr &primitive,
|
||||
const AbstractBasePtrList &args_spec_list);
|
||||
AbstractBasePtr InferImplCSRMV(const AnalysisEnginePtr &, const PrimitivePtr &primitive,
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ ABSTRACT_REPORT_NAME_TRAITS(Type)
|
|||
ABSTRACT_REPORT_NAME_TRAITS(KeywordArg)
|
||||
ABSTRACT_REPORT_NAME_TRAITS(Class)
|
||||
ABSTRACT_REPORT_NAME_TRAITS(RowTensor)
|
||||
ABSTRACT_REPORT_NAME_TRAITS(SparseTensor)
|
||||
ABSTRACT_REPORT_NAME_TRAITS(COOTensor)
|
||||
ABSTRACT_REPORT_NAME_TRAITS(CSRTensor)
|
||||
ABSTRACT_REPORT_NAME_TRAITS(Sequence)
|
||||
|
||||
|
|
|
|||
|
|
@ -316,8 +316,8 @@ AbstractBasePtr InferImplRowTensorAdd(const AnalysisEnginePtr &, const Primitive
|
|||
return args_spec_list[0];
|
||||
}
|
||||
|
||||
AbstractBasePtr InferImplMakeSparseTensor(const AnalysisEnginePtr &, const PrimitivePtr &primitive,
|
||||
const AbstractBasePtrList &args_spec_list) {
|
||||
AbstractBasePtr InferImplMakeCOOTensor(const AnalysisEnginePtr &, const PrimitivePtr &primitive,
|
||||
const AbstractBasePtrList &args_spec_list) {
|
||||
// Inputs: two tensors and a tuple.
|
||||
constexpr auto kMakeSparseInputNum = 3;
|
||||
const std::string op_name = primitive->name();
|
||||
|
|
@ -369,39 +369,39 @@ AbstractBasePtr InferImplMakeSparseTensor(const AnalysisEnginePtr &, const Primi
|
|||
<< dense_shape_value->ToString();
|
||||
}
|
||||
}
|
||||
auto ret = std::make_shared<AbstractSparseTensor>(values->element()->BuildType(), dense_shape_vec);
|
||||
auto ret = std::make_shared<AbstractCOOTensor>(values->element()->BuildType(), dense_shape_vec);
|
||||
ret->set_indices(indices);
|
||||
ret->set_values(values);
|
||||
ret->set_dense_shape(dense_shape);
|
||||
return ret;
|
||||
}
|
||||
|
||||
AbstractBasePtr InferImplSparseTensorGetValues(const AnalysisEnginePtr &, const PrimitivePtr &primitive,
|
||||
const AbstractBasePtrList &args_spec_list) {
|
||||
AbstractBasePtr InferImplCOOTensorGetValues(const AnalysisEnginePtr &, const PrimitivePtr &primitive,
|
||||
const AbstractBasePtrList &args_spec_list) {
|
||||
// Inputs: two tensors and a tuple.
|
||||
const std::string op_name = primitive->name();
|
||||
CheckArgsSize(op_name, args_spec_list, 1);
|
||||
auto sparse_tensor = CheckArg<AbstractSparseTensor>(op_name, args_spec_list, 0);
|
||||
auto sparse_tensor = CheckArg<AbstractCOOTensor>(op_name, args_spec_list, 0);
|
||||
MS_EXCEPTION_IF_NULL(sparse_tensor->values());
|
||||
return sparse_tensor->values();
|
||||
}
|
||||
|
||||
AbstractBasePtr InferImplSparseTensorGetIndices(const AnalysisEnginePtr &, const PrimitivePtr &primitive,
|
||||
const AbstractBasePtrList &args_spec_list) {
|
||||
AbstractBasePtr InferImplCOOTensorGetIndices(const AnalysisEnginePtr &, const PrimitivePtr &primitive,
|
||||
const AbstractBasePtrList &args_spec_list) {
|
||||
// Inputs: two tensors and a tuple.
|
||||
const std::string op_name = primitive->name();
|
||||
CheckArgsSize(op_name, args_spec_list, 1);
|
||||
auto sparse_tensor = CheckArg<AbstractSparseTensor>(op_name, args_spec_list, 0);
|
||||
auto sparse_tensor = CheckArg<AbstractCOOTensor>(op_name, args_spec_list, 0);
|
||||
MS_EXCEPTION_IF_NULL(sparse_tensor->indices());
|
||||
return sparse_tensor->indices();
|
||||
}
|
||||
|
||||
AbstractBasePtr InferImplSparseTensorGetDenseShape(const AnalysisEnginePtr &, const PrimitivePtr &primitive,
|
||||
const AbstractBasePtrList &args_spec_list) {
|
||||
AbstractBasePtr InferImplCOOTensorGetDenseShape(const AnalysisEnginePtr &, const PrimitivePtr &primitive,
|
||||
const AbstractBasePtrList &args_spec_list) {
|
||||
// Inputs: two tensors and a tuple.
|
||||
const std::string op_name = primitive->name();
|
||||
CheckArgsSize(op_name, args_spec_list, 1);
|
||||
auto sparse_tensor = CheckArg<AbstractSparseTensor>(op_name, args_spec_list, 0);
|
||||
auto sparse_tensor = CheckArg<AbstractCOOTensor>(op_name, args_spec_list, 0);
|
||||
MS_EXCEPTION_IF_NULL(sparse_tensor->dense_shape());
|
||||
return sparse_tensor->dense_shape();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -215,11 +215,11 @@ PrimitiveEvalImplMap &GetPrimitiveToEvalImplMap() {
|
|||
{prim::kPrimDebug, R{InferImplDebug, nullptr, true}},
|
||||
// Dynamic shape testing
|
||||
{prim::kPrimGpuConvertToDynamicShape, R{InferImplGpuConvertToDynamicShape, nullptr, true}},
|
||||
// SparseTensor
|
||||
{prim::kPrimMakeSparseTensor, R{InferImplMakeSparseTensor, nullptr, true}},
|
||||
{prim::kPrimSparseTensorGetValues, R{InferImplSparseTensorGetValues, nullptr, true}},
|
||||
{prim::kPrimSparseTensorGetIndices, R{InferImplSparseTensorGetIndices, nullptr, true}},
|
||||
{prim::kPrimSparseTensorGetDenseShape, R{InferImplSparseTensorGetDenseShape, nullptr, true}},
|
||||
// COOTensor
|
||||
{prim::kPrimMakeCOOTensor, R{InferImplMakeCOOTensor, nullptr, true}},
|
||||
{prim::kPrimCOOTensorGetValues, R{InferImplCOOTensorGetValues, nullptr, true}},
|
||||
{prim::kPrimCOOTensorGetIndices, R{InferImplCOOTensorGetIndices, nullptr, true}},
|
||||
{prim::kPrimCOOTensorGetDenseShape, R{InferImplCOOTensorGetDenseShape, nullptr, true}},
|
||||
// RowTensor
|
||||
{prim::kPrimMakeRowTensor, R{InferImplMakeRowTensor, nullptr, true}},
|
||||
{prim::kPrimRowTensorGetValues, R{InferImplRowTensorGetValues, nullptr, true}},
|
||||
|
|
|
|||
|
|
@ -138,6 +138,13 @@ constexpr auto kCSRTensorGetIndptr = "CSRTensorGetIndptr";
|
|||
constexpr auto kCSRTensorGetIndices = "CSRTensorGetIndices";
|
||||
constexpr auto kCSRTensorGetDenseShape = "CSRTensorGetDenseShape";
|
||||
|
||||
// COOTensor
|
||||
constexpr auto kMakeCOOTensor = "MakeCOOTensor";
|
||||
constexpr auto kCOOTensorGetValues = "COOTensorGetValues";
|
||||
constexpr auto kCOOTensorGetIndices = "COOTensorGetIndices";
|
||||
constexpr auto kCOOTensorGetDenseShapes = "COOTensorGetDenseShape";
|
||||
constexpr auto kCOOTensorDenseMatmul = "COOTensorDenseMatmul";
|
||||
|
||||
// Sparse ops
|
||||
constexpr auto kSparseTensorDenseMatmul = "SparseTensorDenseMatmul";
|
||||
constexpr auto kCSRDenseMul = "CSRDenseMul";
|
||||
|
|
@ -565,13 +572,12 @@ MS_CORE_API inline const PrimitivePtr kPrimRowTensorGetDenseShape =
|
|||
std::make_shared<Primitive>("RowTensorGetDenseShape");
|
||||
MS_CORE_API inline const PrimitivePtr kPrimRowTensorAdd = std::make_shared<Primitive>("RowTensorAdd");
|
||||
|
||||
// SparseTensor
|
||||
MS_CORE_API inline const PrimitivePtr kPrimMakeSparseTensor = std::make_shared<Primitive>("MakeSparseTensor");
|
||||
MS_CORE_API inline const PrimitivePtr kPrimSparseTensorGetValues = std::make_shared<Primitive>("SparseTensorGetValues");
|
||||
MS_CORE_API inline const PrimitivePtr kPrimSparseTensorGetIndices =
|
||||
std::make_shared<Primitive>("SparseTensorGetIndices");
|
||||
MS_CORE_API inline const PrimitivePtr kPrimSparseTensorGetDenseShape =
|
||||
std::make_shared<Primitive>("SparseTensorGetDenseShape");
|
||||
// COOTensor
|
||||
MS_CORE_API inline const PrimitivePtr kPrimMakeCOOTensor = std::make_shared<Primitive>(kMakeCOOTensor);
|
||||
MS_CORE_API inline const PrimitivePtr kPrimCOOTensorGetValues = std::make_shared<Primitive>(kCOOTensorGetValues);
|
||||
MS_CORE_API inline const PrimitivePtr kPrimCOOTensorGetIndices = std::make_shared<Primitive>(kCOOTensorGetIndices);
|
||||
MS_CORE_API inline const PrimitivePtr kPrimCOOTensorGetDenseShape =
|
||||
std::make_shared<Primitive>(kCOOTensorGetDenseShapes);
|
||||
|
||||
// CSRTensor
|
||||
MS_CORE_API inline const PrimitivePtr kPrimMakeCSRTensor = std::make_shared<Primitive>(kMakeCSRTensor);
|
||||
|
|
@ -584,6 +590,7 @@ MS_CORE_API inline const PrimitivePtr kPrimCSRTensorGetDenseShape =
|
|||
// Sparse ops
|
||||
MS_CORE_API inline const PrimitivePtr kPrimSparseTensorDenseMatmul =
|
||||
std::make_shared<Primitive>(kSparseTensorDenseMatmul);
|
||||
MS_CORE_API inline const PrimitivePtr kPrimCOOTensorDenseMatmul = std::make_shared<Primitive>(kCOOTensorDenseMatmul);
|
||||
MS_CORE_API inline const PrimitivePtr kPrimCSRDenseMul = std::make_shared<Primitive>(kCSRDenseMul);
|
||||
MS_CORE_API inline const PrimitivePtr kPrimCSRReduceSum = std::make_shared<Primitive>(kCSRReduceSum);
|
||||
MS_CORE_API inline const PrimitivePtr kPrimCSRMV = std::make_shared<Primitive>(kCSRMV);
|
||||
|
|
|
|||
|
|
@ -147,40 +147,40 @@ bool RowTensorType::operator==(const Type &other) const {
|
|||
return *element_type_ == *other_elem_type;
|
||||
}
|
||||
|
||||
TypePtr SparseTensorType::DeepCopy() const {
|
||||
TypePtr COOTensorType::DeepCopy() const {
|
||||
MS_EXCEPTION_IF_NULL(element_type_);
|
||||
if (IsGeneric()) {
|
||||
return std::make_shared<SparseTensorType>();
|
||||
return std::make_shared<COOTensorType>();
|
||||
}
|
||||
return std::make_shared<SparseTensorType>(element_type_->DeepCopy());
|
||||
return std::make_shared<COOTensorType>(element_type_->DeepCopy());
|
||||
}
|
||||
|
||||
std::string SparseTensorType::ToReprString() const {
|
||||
std::string COOTensorType::ToReprString() const {
|
||||
if (element_type_ == nullptr) {
|
||||
return "SparseTensor";
|
||||
return "COOTensor";
|
||||
}
|
||||
return "SparseTensor[" + element_type_->ToReprString() + "]";
|
||||
return "COOTensor[" + element_type_->ToReprString() + "]";
|
||||
}
|
||||
|
||||
std::string SparseTensorType::ToString() const {
|
||||
std::string COOTensorType::ToString() const {
|
||||
if (element_type_ == nullptr) {
|
||||
return "SparseTensor";
|
||||
return "COOTensor";
|
||||
}
|
||||
return "SparseTensor[" + element_type_->ToString() + "]";
|
||||
return "COOTensor[" + element_type_->ToString() + "]";
|
||||
}
|
||||
|
||||
std::string SparseTensorType::DumpText() const {
|
||||
std::string COOTensorType::DumpText() const {
|
||||
if (element_type_ == nullptr) {
|
||||
return "SparseTensor";
|
||||
return "COOTensor";
|
||||
}
|
||||
return "SparseTensor[" + element_type_->DumpText() + "]";
|
||||
return "COOTensor[" + element_type_->DumpText() + "]";
|
||||
}
|
||||
|
||||
bool SparseTensorType::operator==(const Type &other) const {
|
||||
bool COOTensorType::operator==(const Type &other) const {
|
||||
if (!IsSameObjectType(*this, other)) {
|
||||
return false;
|
||||
}
|
||||
auto other_elem_type = static_cast<const SparseTensorType &>(other).element_type_;
|
||||
auto other_elem_type = static_cast<const COOTensorType &>(other).element_type_;
|
||||
if (element_type_ == nullptr && other_elem_type == nullptr) {
|
||||
return true;
|
||||
} else if (element_type_ == nullptr || other_elem_type == nullptr) {
|
||||
|
|
|
|||
|
|
@ -154,29 +154,29 @@ class MS_CORE_API RowTensorType final : public Object {
|
|||
using RowTensorTypePtr = std::shared_ptr<RowTensorType>;
|
||||
|
||||
/// \brief SparseTensorType defines interface for sparse tensor data type.
|
||||
class MS_CORE_API SparseTensorType final : public Object {
|
||||
class MS_CORE_API COOTensorType final : public Object {
|
||||
public:
|
||||
/// \brief Default constructor for SparseTensorType.
|
||||
SparseTensorType() : Object(kObjectTypeSparseTensorType, kObjectTypeUndeterminedType) {}
|
||||
/// \brief Default constructor for COOTensorType.
|
||||
COOTensorType() : Object(kObjectTypeCOOTensorType, kObjectTypeUndeterminedType) {}
|
||||
|
||||
/// \brief Constructor for SparseTensorType.
|
||||
/// \brief Constructor for COOTensorType.
|
||||
///
|
||||
/// \param[in] ele The element of SparseTensorType.
|
||||
explicit SparseTensorType(const TypePtr &ele)
|
||||
: Object(kObjectTypeSparseTensorType, kObjectTypeUndeterminedType, false), element_type_(ele) {}
|
||||
/// \param[in] ele The element of COOTensorType.
|
||||
explicit COOTensorType(const TypePtr &ele)
|
||||
: Object(kObjectTypeCOOTensorType, kObjectTypeUndeterminedType, false), element_type_(ele) {}
|
||||
|
||||
/// \brief Destructor of SparseTensorType.
|
||||
~SparseTensorType() override = default;
|
||||
MS_DECLARE_PARENT(SparseTensorType, Object)
|
||||
/// \brief Destructor of COOTensorType.
|
||||
~COOTensorType() override = default;
|
||||
MS_DECLARE_PARENT(COOTensorType, Object)
|
||||
|
||||
TypeId generic_type_id() const override { return kObjectTypeSparseTensorType; }
|
||||
TypeId generic_type_id() const override { return kObjectTypeCOOTensorType; }
|
||||
|
||||
/// \brief Get the element of SparseTensorType object.
|
||||
/// \brief Get the element of COOTensorType object.
|
||||
///
|
||||
/// \return The element of SparseTensorType object.
|
||||
/// \return The element of COOTensorType object.
|
||||
const TypePtr element() const { return element_type_; }
|
||||
|
||||
/// \brief Set the element of SparseTensorType object.
|
||||
/// \brief Set the element of COOTensorType object.
|
||||
///
|
||||
/// \param[in] element_type Define the element type to be set.
|
||||
void set_element(const TypePtr &element_type) { element_type_ = element_type; }
|
||||
|
|
@ -190,7 +190,7 @@ class MS_CORE_API SparseTensorType final : public Object {
|
|||
private:
|
||||
TypePtr element_type_;
|
||||
};
|
||||
using SparseTensorTypePtr = std::shared_ptr<SparseTensorType>;
|
||||
using COOTensorTypePtr = std::shared_ptr<COOTensorType>;
|
||||
|
||||
/// \brief CSRTensorType defines interface for sparse tensor data type.
|
||||
class MS_CORE_API CSRTensorType : public Object {
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ static mindspore::HashMap<TypeId, std::string> g_type_2_lable{
|
|||
{kObjectTypeKeyword, MS_TYPE2LABLE(kObjectTypeKeyword)},
|
||||
{kObjectTypeTensorType, MS_TYPE2LABLE(kObjectTypeTensorType)},
|
||||
{kObjectTypeRowTensorType, MS_TYPE2LABLE(kObjectTypeRowTensorType)},
|
||||
{kObjectTypeSparseTensorType, MS_TYPE2LABLE(kObjectTypeSparseTensorType)},
|
||||
{kObjectTypeCOOTensorType, MS_TYPE2LABLE(kObjectTypeCOOTensorType)},
|
||||
{kObjectTypeCSRTensorType, MS_TYPE2LABLE(kObjectTypeCSRTensorType)},
|
||||
{kObjectTypeUndeterminedType, MS_TYPE2LABLE(kObjectTypeUndeterminedType)},
|
||||
{kObjectTypeClass, MS_TYPE2LABLE(kObjectTypeClass)},
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ std::string GetExcptionTypeString(TypeId id) {
|
|||
{kMetaTypeObject, "MetaTypeObject"},
|
||||
{kObjectTypeNumber, "Number"},
|
||||
{kObjectTypeRowTensorType, "RowTensor"},
|
||||
{kObjectTypeSparseTensorType, "SparseTensor"},
|
||||
{kObjectTypeCOOTensorType, "COOTensor"},
|
||||
{kObjectTypeUndeterminedType, "Undetermined"},
|
||||
{kObjectTypeClass, "Class"},
|
||||
{kObjectTypeFunction, "Function"},
|
||||
|
|
@ -229,9 +229,9 @@ TypePtr RowTensorStrToType(const std::string &type_name) {
|
|||
return std::make_shared<RowTensorType>(element_type);
|
||||
}
|
||||
|
||||
TypePtr SparseTensorStrToType(const std::string &type_name) {
|
||||
if (type_name == "SparseTensor") {
|
||||
return std::make_shared<SparseTensorType>();
|
||||
TypePtr COOTensorStrToType(const std::string &type_name) {
|
||||
if (type_name == "COOTensor") {
|
||||
return std::make_shared<COOTensorType>();
|
||||
}
|
||||
auto start = type_name.find_first_of('[') + 1;
|
||||
auto end = type_name.find_last_of(']');
|
||||
|
|
@ -243,7 +243,7 @@ TypePtr SparseTensorStrToType(const std::string &type_name) {
|
|||
if (element_type == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
return std::make_shared<SparseTensorType>(element_type);
|
||||
return std::make_shared<COOTensorType>(element_type);
|
||||
}
|
||||
|
||||
TypePtr CSRTensorStrToType(const std::string &type_name) {
|
||||
|
|
@ -417,7 +417,7 @@ TypePtr GetTypeByStringStarts(const std::string &type_name) {
|
|||
{"Tensor", [](const std::string &type_name) -> TypePtr { return TensorStrToType(type_name); }},
|
||||
{"Undetermined", [](const std::string &type_name) -> TypePtr { return UndeterminedStrToType(type_name); }},
|
||||
{"RowTensor", [](const std::string &type_name) -> TypePtr { return RowTensorStrToType(type_name); }},
|
||||
{"SparseTensor", [](const std::string &type_name) -> TypePtr { return SparseTensorStrToType(type_name); }},
|
||||
{"COOTensor", [](const std::string &type_name) -> TypePtr { return COOTensorStrToType(type_name); }},
|
||||
{"CSRTensor", [](const std::string &type_name) -> TypePtr { return CSRTensorStrToType(type_name); }},
|
||||
{"List", [](const std::string &type_name) -> TypePtr { return ListStrToType(type_name); }},
|
||||
{"Tuple", [](const std::string &type_name) -> TypePtr { return TupleStrToType(type_name); }},
|
||||
|
|
|
|||
|
|
@ -15,7 +15,12 @@
|
|||
*/
|
||||
|
||||
#include "ir/tensor.h"
|
||||
|
||||
#include <iomanip>
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
#include <algorithm>
|
||||
|
||||
#include "abstract/utils.h"
|
||||
#include "abstract/abstract_value.h"
|
||||
#include "base/complex_storage.h"
|
||||
|
|
@ -704,5 +709,34 @@ abstract::AbstractBasePtr CSRTensor::ToAbstract() {
|
|||
|
||||
return abs_csr_tensor;
|
||||
}
|
||||
|
||||
std::string COOTensor::ToString() const {
|
||||
std::ostringstream buf;
|
||||
MS_EXCEPTION_IF_NULL(indices_);
|
||||
MS_EXCEPTION_IF_NULL(values_);
|
||||
auto dtype = values_->Dtype();
|
||||
buf << "COOTensor(shape=" << ShapeToString(shape_) << ", dtype=" << dtype->ToString()
|
||||
<< ", indices=" << indices_->ToString() << ", values=" << values_->ToString() << ")";
|
||||
return buf.str();
|
||||
}
|
||||
|
||||
abstract::AbstractBasePtr COOTensor::ToAbstract() {
|
||||
auto dtype = values_->Dtype();
|
||||
if (!IsSubType(dtype, kNumber) && !IsSubType(dtype, kString) && !IsSubType(dtype, kTensorType)) {
|
||||
MS_LOG(EXCEPTION) << "Expect tensor type kNumber or kString or kTensor but got: " << dtype->ToString() << ".";
|
||||
}
|
||||
auto abs_sparse_tensor = std::make_shared<abstract::AbstractCOOTensor>(dtype, shape_);
|
||||
|
||||
abs_sparse_tensor->set_indices(indices_->ToAbstract()->cast<abstract::AbstractTensorPtr>());
|
||||
abs_sparse_tensor->set_values(values_->ToAbstract()->cast<abstract::AbstractTensorPtr>());
|
||||
|
||||
std::vector<abstract::AbstractBasePtr> abstract_shape;
|
||||
std::transform(
|
||||
shape_.begin(), shape_.end(), std::back_inserter(abstract_shape),
|
||||
[](auto shp) -> abstract::AbstractScalarPtr { return std::make_shared<abstract::AbstractScalar>(shp); });
|
||||
abs_sparse_tensor->set_dense_shape(std::make_shared<abstract::AbstractTuple>(abstract_shape));
|
||||
|
||||
return abs_sparse_tensor;
|
||||
}
|
||||
} // namespace tensor
|
||||
} // namespace mindspore
|
||||
|
|
|
|||
|
|
@ -606,6 +606,57 @@ class MS_CORE_API CSRTensor : public MetaSparseTensor {
|
|||
TensorPtr values_;
|
||||
};
|
||||
using CSRTensorPtr = std::shared_ptr<CSRTensor>;
|
||||
|
||||
// COOTensor entity class
|
||||
class MS_CORE_API COOTensor : public MetaSparseTensor {
|
||||
public:
|
||||
abstract::AbstractBasePtr ToAbstract() override;
|
||||
|
||||
/// \brief Create COOTensor with given data type from another tensor.
|
||||
///
|
||||
/// \param[in] indices [Tensor] The indices.
|
||||
/// \param[in] values [Tensor] The values.
|
||||
/// \param[in] shape The shape represented by ShapeVector of the COOTensor.
|
||||
COOTensor(const TensorPtr indices, const TensorPtr values, const ShapeVector &shape)
|
||||
: MetaSparseTensor(values->data_type(), shape), indices_(indices), values_(values) {}
|
||||
|
||||
/// Destructor of COOTensor.
|
||||
~COOTensor() override = default;
|
||||
|
||||
/// \brief Gets COOTensor's indices.
|
||||
///
|
||||
/// \return [TensorPtr] The indices.
|
||||
TensorPtr GetIndices() { return indices_; }
|
||||
|
||||
/// \brief Gets COOTensor's values.
|
||||
///
|
||||
/// \return [TensorPtr] The values.
|
||||
TensorPtr GetValues() { return values_; }
|
||||
|
||||
/// \brief Compare two tensor objects to see if they have same data type, shape and data address.
|
||||
///
|
||||
/// \param[in] tensor The Tensor object to be compared.
|
||||
/// \return True if having same type, shape and data address, otherwise false.
|
||||
bool operator==(const COOTensor &sparse_tensor) const { return &sparse_tensor == this; }
|
||||
|
||||
bool operator==(const Value &other) const override {
|
||||
if (other.isa<COOTensor>()) {
|
||||
auto &other_ = static_cast<const COOTensor &>(other);
|
||||
return *this == other_;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// \brief Get display information of this Tensor.
|
||||
///
|
||||
/// \return The display information of this Tensor.
|
||||
std::string ToString() const override;
|
||||
|
||||
private:
|
||||
TensorPtr indices_;
|
||||
TensorPtr values_;
|
||||
};
|
||||
using COOTensorPtr = std::shared_ptr<COOTensor>;
|
||||
} // namespace tensor
|
||||
} // namespace mindspore
|
||||
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ enum TypeId : int {
|
|||
kObjectTypeKeyword,
|
||||
kObjectTypeTensorType,
|
||||
kObjectTypeRowTensorType,
|
||||
kObjectTypeSparseTensorType,
|
||||
kObjectTypeCOOTensorType,
|
||||
kObjectTypeUndeterminedType,
|
||||
kObjectTypeClass,
|
||||
kObjectTypeDictionary,
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ enum TypeId : int {
|
|||
kObjectTypeKeyword,
|
||||
kObjectTypeTensorType,
|
||||
kObjectTypeRowTensorType,
|
||||
kObjectTypeSparseTensorType,
|
||||
kObjectTypeCOOTensorType,
|
||||
kObjectTypeUndeterminedType,
|
||||
kObjectTypeClass,
|
||||
kObjectTypeDictionary,
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
import ast
|
||||
import math
|
||||
|
||||
from mindspore import RowTensor, SparseTensor, CSRTensor
|
||||
from mindspore import RowTensor, SparseTensor, COOTensor, CSRTensor
|
||||
from mindspore.ops import functional as F, composite as C
|
||||
from mindspore.ops.composite import multitype_ops
|
||||
from mindspore._c_expression import security
|
||||
|
|
@ -158,6 +158,7 @@ convert_object_map = {
|
|||
# user defined
|
||||
RowTensor: F.make_row_tensor,
|
||||
SparseTensor: F.make_sparse_tensor,
|
||||
COOTensor: F.make_coo_tensor,
|
||||
CSRTensor: F.make_csr_tensor
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ from .dtype import Type, int8, byte, int16, short, int32, intc, int64, intp, \
|
|||
from .dump import set_dump
|
||||
from .parameter import Parameter, ParameterTuple
|
||||
from .seed import set_seed, get_seed
|
||||
from .tensor import Tensor, RowTensor, SparseTensor, CSRTensor
|
||||
from .tensor import Tensor, RowTensor, SparseTensor, COOTensor, CSRTensor
|
||||
|
||||
# symbols from dtype
|
||||
__all__ = [
|
||||
|
|
@ -53,7 +53,7 @@ __all__ = [
|
|||
]
|
||||
|
||||
__all__.extend([
|
||||
"Tensor", "RowTensor", "SparseTensor", "CSRTensor", # tensor
|
||||
"Tensor", "RowTensor", "SparseTensor", "COOTensor", "CSRTensor", # tensor
|
||||
'ms_function', # api
|
||||
'Parameter', 'ParameterTuple', # parameter
|
||||
"dtype",
|
||||
|
|
|
|||
|
|
@ -29,7 +29,8 @@ from mindspore import log as logger
|
|||
from mindspore._extends.remote import kernel_build_server
|
||||
from .tensor import Tensor as MsTensor
|
||||
from .tensor import CSRTensor as MsCSRTensor
|
||||
from .._c_expression import GraphExecutor_, Tensor, MetaTensor, CSRTensor, PynativeExecutor_, _ms_memory_recycle
|
||||
from .tensor import COOTensor as MsCOOTensor
|
||||
from .._c_expression import GraphExecutor_, Tensor, MetaTensor, CSRTensor, COOTensor, PynativeExecutor_
|
||||
from .._c_expression import verify_inputs_signature, init_exec_dataset, _set_dataset_mode_config, init_pipeline
|
||||
from ..parallel._ps_context import _is_role_pserver, _is_role_sched
|
||||
from ..parallel._utils import _get_device_num, _get_global_rank, _need_to_full, _check_full_batch, _to_full_tensor, \
|
||||
|
|
@ -65,6 +66,8 @@ def _wrap_func(fn):
|
|||
return MsTensor(data)
|
||||
if isinstance(data, CSRTensor) and not isinstance(data, MsCSRTensor):
|
||||
return MsCSRTensor(csr_tensor=data)
|
||||
if isinstance(data, COOTensor) and not isinstance(data, MsCOOTensor):
|
||||
return MsCOOTensor(coo_tensor=data)
|
||||
if isinstance(data, tuple):
|
||||
return tuple(_convert_data(x) for x in data)
|
||||
if isinstance(data, list):
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ type_none = typing.TypeNone()
|
|||
|
||||
tensor = typing.TensorType()
|
||||
index_slices = typing.RowTensorType()
|
||||
sparse_tensor = typing.SparseTensorType()
|
||||
coo_tensor = typing.COOTensorType()
|
||||
csr_tensor = typing.CSRTensorType()
|
||||
undetermined = typing.UndeterminedType()
|
||||
|
||||
|
|
|
|||
|
|
@ -22,11 +22,12 @@ from . import dtype as mstype
|
|||
from ._register_for_tensor import tensor_operator_registry
|
||||
from .._c_expression import Tensor as Tensor_
|
||||
from .._c_expression import CSRTensor as CSRTensor_
|
||||
from .._c_expression import COOTensor as COOTensor_
|
||||
from .._c_expression import PynativeExecutor_
|
||||
from .._checkparam import Validator as validator
|
||||
from .._checkparam import Rel
|
||||
|
||||
__all__ = ['Tensor', 'RowTensor', 'SparseTensor', 'CSRTensor']
|
||||
__all__ = ['Tensor', 'RowTensor', 'SparseTensor', 'COOTensor', 'CSRTensor']
|
||||
np_types = (np.int8, np.int16, np.int32, np.int64,
|
||||
np.uint8, np.uint16, np.uint32, np.uint64, np.float16,
|
||||
np.float32, np.float64, np.bool_, np.complex64, np.complex128)
|
||||
|
|
@ -2318,7 +2319,7 @@ class RowTensor:
|
|||
return self.__dense_shape
|
||||
|
||||
|
||||
class SparseTensor:
|
||||
class SparseTensor(COOTensor_):
|
||||
"""
|
||||
A sparse representation of a set of nonzero elements from a tensor at given indices.
|
||||
|
||||
|
|
@ -2337,7 +2338,8 @@ class SparseTensor:
|
|||
[0, 0, 0, 0]]
|
||||
|
||||
Note:
|
||||
SparseTensor is not supported in Pynative mode at the moment.
|
||||
The interface is deprecated from version 1.7 and will be removed in a future version.
|
||||
Please use 'COOTensor' instead.
|
||||
|
||||
Args:
|
||||
indices (Tensor): A 2-D integer Tensor of shape `[N, ndims]`,
|
||||
|
|
@ -2345,53 +2347,122 @@ class SparseTensor:
|
|||
the SparseTensor, respectively.
|
||||
values (Tensor): A 1-D tensor of any type and shape `[N]`, which
|
||||
supplies the values for each element in `indices`.
|
||||
dense_shape (tuple(int)): A integer tuple of size `ndims`,
|
||||
which specifies the dense_shape of the sparse tensor.
|
||||
shape (tuple(int)): A integer tuple of size `ndims`,
|
||||
which specifies the shape of the sparse tensor.
|
||||
|
||||
Returns:
|
||||
SparseTensor, composed of `indices`, `values`, and `dense_shape`.
|
||||
SparseTensor, composed of `indices`, `values`, and `shape`.
|
||||
|
||||
Examples:
|
||||
>>> import mindspore as ms
|
||||
>>> import mindspore.nn as nn
|
||||
>>> from mindspore import Tensor, SparseTensor
|
||||
>>> class Net(nn.Cell):
|
||||
... def __init__(self, dense_shape):
|
||||
... super(Net, self).__init__()
|
||||
... self.dense_shape = dense_shape
|
||||
... def construct(self, indices, values):
|
||||
... x = SparseTensor(indices, values, self.dense_shape)
|
||||
... return x.values, x.indices, x.dense_shape
|
||||
>>>
|
||||
>>> indices = Tensor([[0, 1], [1, 2]])
|
||||
>>> values = Tensor([1, 2], dtype=ms.float32)
|
||||
>>> out = Net((3, 4))(indices, values)
|
||||
>>> print(out[0])
|
||||
>>> shape = (3, 4)
|
||||
>>> x = SparseTensor(indices, values, shape)
|
||||
>>> print(x.values)
|
||||
[1. 2.]
|
||||
>>> print(out[1])
|
||||
>>> print(x.indices)
|
||||
[[0 1]
|
||||
[1 2]]
|
||||
>>> print(out[2])
|
||||
>>> print(x.shape)
|
||||
(3, 4)
|
||||
"""
|
||||
|
||||
def __init__(self, indices, values, dense_shape):
|
||||
"Init SparseTensor"
|
||||
self.__indices = indices
|
||||
self.__values = values
|
||||
self.__dense_shape = dense_shape
|
||||
def __init__(self, indices=None, values=None, shape=None, coo_tensor=None):
|
||||
"Init COOTensor"
|
||||
print("WARNING: 'SparseTensor' is deprecated from version 1.7 and will be removed in a future version. " +
|
||||
"Please use 'COOTensor' instead.")
|
||||
if indices is None and values is None and shape is None and coo_tensor is not None:
|
||||
if not isinstance(coo_tensor, (COOTensor, COOTensor_)):
|
||||
raise TypeError("If only one input provided, it must be a COOTensor.")
|
||||
COOTensor_.__init__(self, coo_tensor)
|
||||
else:
|
||||
if not (isinstance(indices, Tensor) and isinstance(values, Tensor) and isinstance(shape, tuple)):
|
||||
raise TypeError("Inputs must follow: COOTensor(indices, values, shape).")
|
||||
COOTensor_.__init__(self, indices, values, shape)
|
||||
|
||||
@property
|
||||
def indices(self):
|
||||
return self.__indices
|
||||
return Tensor(self._indices)
|
||||
|
||||
@property
|
||||
def values(self):
|
||||
return self.__values
|
||||
return Tensor(self._values)
|
||||
|
||||
@property
|
||||
def dense_shape(self):
|
||||
return self.__dense_shape
|
||||
def shape(self):
|
||||
return self._shape
|
||||
|
||||
|
||||
class COOTensor(COOTensor_):
|
||||
"""
|
||||
A sparse representation of a set of nonzero elements from a tensor at given indices.
|
||||
|
||||
For a tensor dense, its COOTensor(indices, values, dense_shape) has
|
||||
`dense[indices[i]] = values[i]`.
|
||||
|
||||
For example, if indices is [[0, 1], [1, 2]], values is [1, 2], dense_shape is
|
||||
(3, 4), then the dense representation of the sparse tensor will be:
|
||||
|
||||
.. code-block::
|
||||
|
||||
[[0, 1, 0, 0],
|
||||
[0, 0, 2, 0],
|
||||
[0, 0, 0, 0]]
|
||||
|
||||
Args:
|
||||
indices (Tensor): A 2-D integer Tensor of shape `[N, ndims]`,
|
||||
where N and ndims are the number of `values` and number of dimensions in
|
||||
the COOTensor, respectively.
|
||||
values (Tensor): A 1-D tensor of any type and shape `[N]`, which
|
||||
supplies the values for each element in `indices`.
|
||||
shape (tuple(int)): A integer tuple of size `ndims`,
|
||||
which specifies the dense_shape of the sparse tensor.
|
||||
|
||||
Returns:
|
||||
COOTensor, composed of `indices`, `values`, and `shape`.
|
||||
|
||||
Examples:
|
||||
>>> import mindspore as ms
|
||||
>>> import mindspore.nn as nn
|
||||
>>> from mindspore import Tensor, COOTensor
|
||||
>>> indices = Tensor([[0, 1], [1, 2]])
|
||||
>>> values = Tensor([1, 2], dtype=ms.float32)
|
||||
>>> shape = (3, 4)
|
||||
>>> x = COOTensor(indices, values, shape)
|
||||
>>> print(x.values)
|
||||
[1. 2.]
|
||||
>>> print(x.indices)
|
||||
[[0 1]
|
||||
[1 2]]
|
||||
>>> print(x.shape)
|
||||
(3, 4)
|
||||
"""
|
||||
|
||||
def __init__(self, indices=None, values=None, shape=None, coo_tensor=None):
|
||||
"Init COOTensor"
|
||||
if indices is None and values is None and shape is None and coo_tensor is not None:
|
||||
if not isinstance(coo_tensor, (COOTensor, COOTensor_)):
|
||||
raise TypeError("If only one input provided, it must be a COOTensor.")
|
||||
COOTensor_.__init__(self, coo_tensor)
|
||||
else:
|
||||
if not (isinstance(indices, Tensor) and isinstance(values, Tensor) and isinstance(shape, tuple)):
|
||||
raise TypeError("Inputs must follow: COOTensor(indices, values, shape).")
|
||||
COOTensor_.__init__(self, indices, values, shape)
|
||||
|
||||
@property
|
||||
def indices(self):
|
||||
return Tensor(self._indices)
|
||||
|
||||
@property
|
||||
def values(self):
|
||||
return Tensor(self._values)
|
||||
|
||||
@property
|
||||
def shape(self):
|
||||
return self._shape
|
||||
|
||||
|
||||
class CSRTensor(CSRTensor_):
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ from ..cell import Cell
|
|||
|
||||
class SparseToDense(Cell):
|
||||
"""
|
||||
Converts a sparse tensor into dense.
|
||||
Converts a sparse tensor(COOTensor) into dense.
|
||||
|
||||
In Python, for the ease of use, three tensors are collected into a SparseTensor class.
|
||||
MindSpore uses three independent dense tensors: indices, value and dense shape to represent the sparse tensor.
|
||||
|
|
@ -27,7 +27,7 @@ class SparseToDense(Cell):
|
|||
before being passed to the OPS below.
|
||||
|
||||
Inputs:
|
||||
- **sparse_tensor** (:class:`mindspore.SparseTensor`): the sparse tensor to convert.
|
||||
- **coo_tensor** (:class:`mindspore.COOTensor`): the sparse COOTensor to convert.
|
||||
|
||||
Outputs:
|
||||
Tensor, converted from sparse tensor.
|
||||
|
|
@ -35,24 +35,31 @@ class SparseToDense(Cell):
|
|||
Raises:
|
||||
TypeError: If `sparse_tensor.indices` is not a Tensor.
|
||||
TypeError: If `sparse_tensor.values` is not a Tensor.
|
||||
TypeError: If `sparse_tensor.dense_shape` is not a tuple.
|
||||
TypeError: If `sparse_tensor.shape` is not a tuple.
|
||||
|
||||
Supported Platforms:
|
||||
``CPU``
|
||||
|
||||
Examples:
|
||||
>>> import mindspore as ms
|
||||
>>> from mindspore import Tensor, SparseTensor
|
||||
>>> from mindspore import Tensor, COOTensor
|
||||
>>> import mindspore.nn as nn
|
||||
>>> import mindspore.context as context
|
||||
>>> context.set_context(mode=context.PYNATIVE_MODE)
|
||||
>>> indices = Tensor([[0, 1], [1, 2]])
|
||||
>>> values = Tensor([1, 2], dtype=ms.int32)
|
||||
>>> dense_shape = (3, 4)
|
||||
>>> sparse_tensor = SparseTensor(indices, values, dense_shape)
|
||||
>>> sparse_to_dense = nn.SparseToDense()
|
||||
>>> result = sparse_to_dense(sparse_tensor)
|
||||
>>> print(result)
|
||||
>>> class Net(nn.Cell):
|
||||
... def __init__(self, dense_shape):
|
||||
... super(Net, self).__init__()
|
||||
... self.dense_shape = dense_shape
|
||||
... self.op = nn.SparseToDense()
|
||||
...
|
||||
... def construct(self, indices, values):
|
||||
... x = COOTensor(indices, values, self.dense_shape)
|
||||
... return self.op(x)
|
||||
...
|
||||
>>> print(Net(dense_shape)(indices, values))
|
||||
[[0 1 0 0]
|
||||
[0 0 2 0]
|
||||
[0 0 0 0]]
|
||||
|
|
@ -66,7 +73,7 @@ class SparseToDense(Cell):
|
|||
def construct(self, sparse_tensor):
|
||||
return self.sparse_to_dense(sparse_tensor.indices,
|
||||
sparse_tensor.values,
|
||||
sparse_tensor.dense_shape)
|
||||
sparse_tensor.shape)
|
||||
|
||||
|
||||
class SparseTensorDenseMatmul(Cell):
|
||||
|
|
|
|||
|
|
@ -23,29 +23,29 @@ from .grad_base import bprops, bprop_getters
|
|||
# Unused parameters are placeholders.
|
||||
|
||||
|
||||
@bprops.register("MakeSparseTensor")
|
||||
def bprop_make_sparse_tensor(indices, values, dense_shape, out, dout):
|
||||
"""Backpropagator for primitive `MakeSparseTensor`."""
|
||||
return zeros_like(indices), F.sparse_tensor_get_values(dout), ()
|
||||
@bprops.register("MakeCOOTensor")
|
||||
def bprop_make_coo_tensor(indices, values, dense_shape, out, dout):
|
||||
"""Backpropagator for primitive `MakeCOOTensor`."""
|
||||
return zeros_like(indices), F.coo_tensor_get_values(dout), ()
|
||||
|
||||
|
||||
@bprops.register("SparseTensorGetIndices")
|
||||
@bprops.register("COOTensorGetIndices")
|
||||
def bprop_sparse_tensor_get_indices(sparse_tensor, out, dout):
|
||||
"""Backpropagator for primitive `SparseTensorGetIndices`."""
|
||||
"""Backpropagator for primitive `COOTensorGetIndices`."""
|
||||
return (zeros_like(sparse_tensor),)
|
||||
|
||||
|
||||
@bprops.register("SparseTensorGetValues")
|
||||
@bprops.register("COOTensorGetValues")
|
||||
def bprop_sparse_tensor_get_values(sparse_tensor, out, dout):
|
||||
"""Backpropagator for primitive `SparseTensorGetValues`."""
|
||||
return F.make_sparse_tensor(F.sparse_tensor_get_indices(sparse_tensor),
|
||||
dout,
|
||||
F.sparse_tensor_get_dense_shape(sparse_tensor))
|
||||
"""Backpropagator for primitive `COOTensorGetValues`."""
|
||||
return F.make_coo_tensor(F.coo_tensor_get_indices(sparse_tensor),
|
||||
dout,
|
||||
F.coo_tensor_get_dense_shape(sparse_tensor))
|
||||
|
||||
|
||||
@bprops.register("SparseTensorGetDenseShape")
|
||||
@bprops.register("COOTensorrGetDenseShape")
|
||||
def bprop_sparse_tensor_get_dense_shape(sparse_tensor, out, dout):
|
||||
"""Backpropagator for primitive `SparseTensorGetDenseShape`."""
|
||||
"""Backpropagator for primitive `COOTensorGetDenseShape`."""
|
||||
return (zeros_like(sparse_tensor),)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -48,14 +48,14 @@ def _ones_like_tensor(x):
|
|||
return P.Fill()(P.DType()(x), P.Shape()(x), 1.0)
|
||||
|
||||
|
||||
@ones_like_leaf.register("SparseTensor")
|
||||
def _ones_like_sparse_tensor(x):
|
||||
@ones_like_leaf.register("COOTensor")
|
||||
def _ones_like_coo_tensor(x):
|
||||
"""Returns a tensor with the same shape and dtype as x and all elements are 1."""
|
||||
values_ = F.sparse_tensor_get_values(x)
|
||||
values_ = F.coo_tensor_get_values(x)
|
||||
values = P.Fill()(P.DType()(values_),
|
||||
P.Shape()(values_),
|
||||
1.0)
|
||||
return F.make_sparse_tensor(F.sparse_tensor_get_indices(x), values, F.sparse_tensor_get_dense_shape(x))
|
||||
return F.make_coo_tensor(F.coo_tensor_get_indices(x), values, F.coo_tensor_get_dense_shape(x))
|
||||
|
||||
|
||||
@ones_like_leaf.register("Function")
|
||||
|
|
|
|||
|
|
@ -601,10 +601,17 @@ row_tensor_get_indices = Primitive('RowTensorGetIndices')
|
|||
row_tensor_get_dense_shape = Primitive('RowTensorGetDenseShape')
|
||||
row_tensor_add = Primitive('RowTensorAdd')
|
||||
|
||||
make_sparse_tensor = Primitive('MakeSparseTensor')
|
||||
sparse_tensor_get_values = Primitive('SparseTensorGetValues')
|
||||
sparse_tensor_get_indices = Primitive('SparseTensorGetIndices')
|
||||
sparse_tensor_get_dense_shape = Primitive('SparseTensorGetDenseShape')
|
||||
make_coo_tensor = Primitive('MakeCOOTensor')
|
||||
coo_tensor_get_values = Primitive('COOTensorGetValues')
|
||||
coo_tensor_get_indices = Primitive('COOTensorGetIndices')
|
||||
coo_tensor_get_dense_shape = Primitive('COOTensorGetDenseShape')
|
||||
|
||||
def make_sparse_tensor(indices, values, dense_shape):
|
||||
"""Call make_coo_tensor in this function."""
|
||||
print("WARNING: 'SparseTensor' is deprecated from version 1.7 and will be removed in a future version. " +
|
||||
"Please use 'COOTensor' instead.")
|
||||
return make_coo_tensor(indices, values, dense_shape)
|
||||
|
||||
|
||||
make_csr_tensor = Primitive('MakeCSRTensor')
|
||||
csr_tensor_get_values = Primitive('CSRTensorGetValues')
|
||||
|
|
|
|||
|
|
@ -0,0 +1,93 @@
|
|||
# Copyright 2022 Huawei Technologies Co., Ltd
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# ============================================================================
|
||||
"""smoke tests for COO operations"""
|
||||
|
||||
import pytest
|
||||
import numpy as np
|
||||
|
||||
from mindspore import Tensor, COOTensor, ms_function, nn, context
|
||||
from mindspore.common import dtype as mstype
|
||||
|
||||
|
||||
context.set_context(mode=context.GRAPH_MODE)
|
||||
|
||||
|
||||
def compare_coo(coo1, coo2):
|
||||
assert isinstance(coo1, COOTensor)
|
||||
assert isinstance(coo2, COOTensor)
|
||||
assert (coo1.indices.asnumpy() == coo2.indices.asnumpy()).all()
|
||||
assert (coo1.values.asnumpy() == coo2.values.asnumpy()).all()
|
||||
assert coo1.shape == coo2.shape
|
||||
|
||||
|
||||
@pytest.mark.level0
|
||||
@pytest.mark.platform_arm_ascend_training
|
||||
@pytest.mark.platform_x86_ascend_training
|
||||
@pytest.mark.platform_x86_gpu_training
|
||||
@pytest.mark.env_onecard
|
||||
def test_make_coo():
|
||||
"""
|
||||
Feature: Test COOTensor Constructor in Graph and PyNative.
|
||||
Description: Test COOTensor(indices, values, shape) and COOTensor(COOTensor)
|
||||
Expectation: Success.
|
||||
"""
|
||||
indices = Tensor([[0, 1], [1, 2]])
|
||||
values = Tensor([1, 2], dtype=mstype.float32)
|
||||
dense_shape = (3, 4)
|
||||
|
||||
def test_pynative():
|
||||
return COOTensor(indices, values, dense_shape)
|
||||
test_graph = ms_function(test_pynative)
|
||||
|
||||
coo1 = test_pynative()
|
||||
coo2 = test_graph()
|
||||
compare_coo(coo1, coo2)
|
||||
coo3 = COOTensor(coo_tensor=coo2)
|
||||
compare_coo(coo3, coo2)
|
||||
|
||||
|
||||
@pytest.mark.level0
|
||||
@pytest.mark.platform_arm_ascend_training
|
||||
@pytest.mark.platform_x86_ascend_training
|
||||
@pytest.mark.platform_x86_gpu_training
|
||||
@pytest.mark.env_onecard
|
||||
def test_coo_tensor_in_while():
|
||||
"""
|
||||
Feature: Test COOTensor in while loop.
|
||||
Description: Test COOTensor computation in while loop.
|
||||
Expectation: Success.
|
||||
"""
|
||||
class COOTensorWithControlWhile(nn.Cell):
|
||||
def __init__(self, shape):
|
||||
super().__init__()
|
||||
self.shape = shape
|
||||
|
||||
@ms_function
|
||||
def construct(self, a, b, indices, values):
|
||||
x = COOTensor(indices, values, self.shape)
|
||||
while a > b:
|
||||
x = COOTensor(indices, values, self.shape)
|
||||
b = b + 1
|
||||
return x
|
||||
a = Tensor(3, mstype.int32)
|
||||
b = Tensor(0, mstype.int32)
|
||||
indices = Tensor([[0, 1], [1, 2]])
|
||||
values = Tensor([1, 2], dtype=mstype.float32)
|
||||
shape = (3, 4)
|
||||
net = COOTensorWithControlWhile(shape)
|
||||
out = net(a, b, indices, values)
|
||||
assert np.allclose(out.indices.asnumpy(), indices.asnumpy(), .0, .0)
|
||||
assert np.allclose(out.values.asnumpy(), values.asnumpy(), .0, .0)
|
||||
assert out.shape == shape
|
||||
|
|
@ -270,7 +270,7 @@ def test_csr_ops():
|
|||
@pytest.mark.platform_x86_gpu_training
|
||||
@pytest.mark.platform_x86_cpu
|
||||
@pytest.mark.env_onecard
|
||||
def test_csrtensor_export_mindir():
|
||||
def test_csrtensor_export_and_import_mindir():
|
||||
"""
|
||||
Feature: Test exporting and loading CSRTensor MindIR.
|
||||
Description: Test export and load.
|
||||
|
|
@ -308,7 +308,7 @@ def test_csrtensor_export_mindir():
|
|||
@pytest.mark.level0
|
||||
@pytest.mark.platform_x86_gpu_training
|
||||
@pytest.mark.env_onecard
|
||||
def test_csrops_export_mindir():
|
||||
def test_csrops_export_and_import_mindir():
|
||||
"""
|
||||
Feature: Test exporting and loading CSRTensor MindIR in a net.
|
||||
Description: Test export and load.
|
||||
|
|
|
|||
|
|
@ -1173,10 +1173,10 @@ def test_row_tensor(tag):
|
|||
def test_sparse_tensor(tag):
|
||||
""" test_add_zero """
|
||||
fns = FnDict()
|
||||
make_sparse_tensor = Primitive('MakeSparseTensor')
|
||||
sparse_tensor_get_values = Primitive('SparseTensorGetValues')
|
||||
sparse_tensor_get_indices = Primitive('SparseTensorGetIndices')
|
||||
sparse_tensor_get_dense_shape = Primitive('SparseTensorGetDenseShape')
|
||||
make_sparse_tensor = Primitive('MakeCOOTensor')
|
||||
sparse_tensor_get_values = Primitive('COOTensorGetValues')
|
||||
sparse_tensor_get_indices = Primitive('COOTensorGetIndices')
|
||||
sparse_tensor_get_dense_shape = Primitive('COOTensorGetDenseShape')
|
||||
|
||||
@fns
|
||||
def before_get_indices(x, y, z):
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ import pytest
|
|||
import mindspore as ms
|
||||
import mindspore.nn as nn
|
||||
from mindspore.ops import composite as C
|
||||
from mindspore import Tensor, SparseTensor, context
|
||||
from mindspore import Tensor, COOTensor, context
|
||||
|
||||
@pytest.fixture(scope="module", autouse=True)
|
||||
def setup_teardown():
|
||||
|
|
@ -40,24 +40,34 @@ class MakeSparseTensor(nn.Cell):
|
|||
super(MakeSparseTensor, self).__init__()
|
||||
self.dense_shape = dense_shape
|
||||
def construct(self, indices, values):
|
||||
ret = (SparseTensor(indices, values, self.dense_shape),)
|
||||
ret = (COOTensor(indices, values, self.dense_shape),)
|
||||
return ret[0]
|
||||
|
||||
|
||||
def test_sparse_tensor_make_sparse_tensor():
|
||||
def test_sparse_tensor_make_coo_tensor():
|
||||
"""
|
||||
Feature: Test MakeCOOTensor.
|
||||
Description: Test MakeCOOTensor.
|
||||
Expectation: Success.
|
||||
"""
|
||||
indices = Tensor([[0, 1], [1, 2]])
|
||||
values = Tensor([1, 2], dtype=ms.float32)
|
||||
MakeSparseTensor((3, 4))(indices, values)
|
||||
|
||||
|
||||
def test_sparse_tensor_attr():
|
||||
"""
|
||||
Feature: Test GetAttr.
|
||||
Description: Test GetAttr in COOTensor (values, indices, dense_shape).
|
||||
Expectation: Success.
|
||||
"""
|
||||
class SparseTensorGetAttr(nn.Cell):
|
||||
def __init__(self):
|
||||
super(SparseTensorGetAttr, self).__init__()
|
||||
self.dense_shape = (3, 4)
|
||||
def construct(self, indices, values):
|
||||
x = SparseTensor(indices, values, self.dense_shape)
|
||||
return x.values, x.indices, x.dense_shape
|
||||
x = COOTensor(indices, values, self.dense_shape)
|
||||
return x.values, x.indices, x.shape
|
||||
|
||||
indices = Tensor([[0, 1], [1, 2]])
|
||||
values = Tensor([1, 2], dtype=ms.float32)
|
||||
|
|
@ -66,6 +76,11 @@ def test_sparse_tensor_attr():
|
|||
|
||||
|
||||
def test_sparse_tensor_indices_dim_greater_than_dense_shape_dim():
|
||||
"""
|
||||
Feature: Test MakeSparseTensor.
|
||||
Description: Test sparse tensor indices dim greater than dense shape dim.
|
||||
Expectation: Success.
|
||||
"""
|
||||
indices = Tensor(np.array([[0, 0, 0], [0, 0, 1]], dtype=np.int32))
|
||||
values = Tensor(np.array([100, 200], dtype=np.float32))
|
||||
dense_shape = (2, 2)
|
||||
|
|
@ -74,6 +89,11 @@ def test_sparse_tensor_indices_dim_greater_than_dense_shape_dim():
|
|||
|
||||
|
||||
def test_sparse_tensor_indices_dim_less_than_dense_shape_dim():
|
||||
"""
|
||||
Feature: Test MakeSparseTensor.
|
||||
Description: Test sparse tensor indices dim less than dense shape dim.
|
||||
Expectation: Success.
|
||||
"""
|
||||
indices = Tensor(np.array([[0, 0], [0, 1]], dtype=np.int32))
|
||||
values = Tensor(np.array([100, 200], dtype=np.float32))
|
||||
dense_shape = (2, 2, 2)
|
||||
|
|
@ -82,13 +102,18 @@ def test_sparse_tensor_indices_dim_less_than_dense_shape_dim():
|
|||
|
||||
|
||||
def test_sparse_tensor_to_tensor():
|
||||
"""
|
||||
Feature: Test nn.SparseToDense.
|
||||
Description: Test COOTensor to dense tensor.
|
||||
Expectation: Success.
|
||||
"""
|
||||
class SparseToDenseCell(nn.Cell):
|
||||
def __init__(self, dense_shape):
|
||||
super(SparseToDenseCell, self).__init__()
|
||||
self.dense_shape = dense_shape
|
||||
self.sparse_to_dense = nn.SparseToDense()
|
||||
def construct(self, indices, values):
|
||||
sparse = SparseTensor(indices, values, self.dense_shape)
|
||||
sparse = COOTensor(indices, values, self.dense_shape)
|
||||
return self.sparse_to_dense(sparse)
|
||||
|
||||
indices = Tensor([[0, 1], [1, 2]])
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
import pytest
|
||||
import mindspore as ms
|
||||
import mindspore.nn as nn
|
||||
from mindspore import context, Tensor, RowTensor, SparseTensor
|
||||
from mindspore import context, Tensor, RowTensor, COOTensor
|
||||
from mindspore.ops import composite as C
|
||||
|
||||
@pytest.fixture(scope="module", autouse=True)
|
||||
|
|
@ -42,6 +42,11 @@ class GradWrap(nn.Cell):
|
|||
|
||||
|
||||
def test_row_tensor_attr():
|
||||
"""
|
||||
Feature: Test RowTensor.
|
||||
Description: Test RowTensor GetAttr.
|
||||
Expectation: Success.
|
||||
"""
|
||||
class RowTensorGetAttr(nn.Cell):
|
||||
def __init__(self, dense_shape):
|
||||
super(RowTensorGetAttr, self).__init__()
|
||||
|
|
@ -56,13 +61,18 @@ def test_row_tensor_attr():
|
|||
|
||||
|
||||
def test_sparse_tensor_attr():
|
||||
"""
|
||||
Feature: Test COOTensor.
|
||||
Description: Test COOTensor GetAttr.
|
||||
Expectation: Success.
|
||||
"""
|
||||
class SparseTensorGetAttr(nn.Cell):
|
||||
def __init__(self):
|
||||
super(SparseTensorGetAttr, self).__init__()
|
||||
self.dense_shape = (3, 4)
|
||||
def construct(self, indices, values):
|
||||
x = SparseTensor(indices, values, self.dense_shape)
|
||||
return x.values, x.indices, x.dense_shape
|
||||
x = COOTensor(indices, values, self.dense_shape)
|
||||
return x.values, x.indices, x.shape
|
||||
|
||||
indices = Tensor([[0, 1], [1, 2]])
|
||||
values = Tensor([1, 2], dtype=ms.float32)
|
||||
|
|
|
|||
Loading…
Reference in New Issue