change sparsetensor to cootensor

This commit is contained in:
wangrao124 2021-12-23 19:11:33 +08:00
parent a4465947b0
commit 9dfc703f7a
47 changed files with 640 additions and 249 deletions

View File

@ -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` 组成。

View File

@ -79,7 +79,7 @@ typedef enum TypeIdC {
kObjectTypeKeyword,
kObjectTypeTensorType,
kObjectTypeRowTensorType,
kObjectTypeSparseTensorType,
kObjectTypeCOOTensorType,
kObjectTypeUndeterminedType,
kObjectTypeClass,
kObjectTypeDictionary,

View File

@ -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());

View File

@ -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.

View File

@ -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();
}

View File

@ -56,7 +56,7 @@ typedef enum MsTypeId : unsigned int {
kObjectTypeKeyword,
kObjectTypeTensorType,
kObjectTypeRowTensorType,
kObjectTypeSparseTensorType,
kObjectTypeCOOTensorType,
kObjectTypeUndeterminedType,
kObjectTypeClass,
kObjectTypeDictionary,

View File

@ -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);
}

View File

@ -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",

View File

@ -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;
}
};

View File

@ -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,
{

View File

@ -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());

View File

@ -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) {

View File

@ -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.");

View File

@ -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

View File

@ -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

View File

@ -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()},

View File

@ -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

View File

@ -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.

View File

@ -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);

View File

@ -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;

View File

@ -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,

View File

@ -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)

View File

@ -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();
}

View File

@ -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}},

View File

@ -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);

View File

@ -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) {

View File

@ -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 {

View File

@ -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)},

View File

@ -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); }},

View File

@ -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

View File

@ -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

View File

@ -47,7 +47,7 @@ enum TypeId : int {
kObjectTypeKeyword,
kObjectTypeTensorType,
kObjectTypeRowTensorType,
kObjectTypeSparseTensorType,
kObjectTypeCOOTensorType,
kObjectTypeUndeterminedType,
kObjectTypeClass,
kObjectTypeDictionary,

View File

@ -48,7 +48,7 @@ enum TypeId : int {
kObjectTypeKeyword,
kObjectTypeTensorType,
kObjectTypeRowTensorType,
kObjectTypeSparseTensorType,
kObjectTypeCOOTensorType,
kObjectTypeUndeterminedType,
kObjectTypeClass,
kObjectTypeDictionary,

View File

@ -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
}

View File

@ -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",

View File

@ -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):

View File

@ -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()

View File

@ -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_):

View File

@ -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):

View File

@ -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),)

View File

@ -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")

View File

@ -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')

View File

@ -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

View File

@ -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.

View File

@ -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):

View File

@ -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]])

View File

@ -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)