Skip to content

[mlir][sparse] add a forwarding insertion to SparseTensorStorage #68939

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Oct 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions mlir/include/mlir/Dialect/SparseTensor/IR/Enums.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,11 +143,10 @@ constexpr bool isComplexPrimaryType(PrimaryType valTy) {
/// The actions performed by @newSparseTensor.
enum class Action : uint32_t {
kEmpty = 0,
// newSparseTensor no longer handles `kFromFile=1`, so we leave this
// number reserved to help catch any code that still needs updating.
kEmptyForward = 1,
kFromCOO = 2,
kSparseToSparse = 3,
kEmptyCOO = 4,
kFuture = 4, // not used
kToCOO = 5,
kToIterator = 6,
kPack = 7,
Expand Down
189 changes: 114 additions & 75 deletions mlir/include/mlir/ExecutionEngine/SparseTensor/Storage.h

Large diffs are not rendered by default.

35 changes: 16 additions & 19 deletions mlir/include/mlir/ExecutionEngine/SparseTensorRuntime.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,22 +37,20 @@ extern "C" {
//
//===----------------------------------------------------------------------===//

/// The @newSparseTensor function for constructing a new sparse tensor.
/// This is the "swiss army knife" method for materializing sparse
/// tensors into the computation. The types of the `ptr` argument and
/// the result depend on the action, as explained in the following table
/// (where "STS" means a sparse-tensor-storage object, "COO" means
/// a coordinate-scheme object, and "Iterator" means an iterator object).
///
/// Action: `ptr`: Returns:
/// kEmpty unused STS, empty
/// kEmptyCOO unused COO, empty
/// kFromFile char* filename STS, read from the file
/// kEmpty - STS, empty
/// kEmptyForward - STS, empty, with forwarding COO
/// kFromCOO COO STS, copied from the COO source
/// kToCOO STS COO, copied from the STS source
/// kSparseToSparse STS STS, copied from the STS source
/// kToIterator STS Iterator, call @getNext to use and
/// @delSparseTensorIterator to free.
/// kToCOO STS COO, copied from the STS source
/// kToIterator STS Iterator (@getNext/@delSparseTensorIterator)
/// kPack buffers STS, from level buffers
MLIR_CRUNNERUTILS_EXPORT void *_mlir_ciface_newSparseTensor( // NOLINT
StridedMemRefType<index_type, 1> *dimSizesRef,
StridedMemRefType<index_type, 1> *lvlSizesRef,
Expand Down Expand Up @@ -84,19 +82,15 @@ MLIR_SPARSETENSOR_FOREVERY_O(DECL_SPARSEPOSITIONS)
MLIR_SPARSETENSOR_FOREVERY_O(DECL_SPARSECOORDINATES)
#undef DECL_SPARSECOORDINATES

/// Coordinate-scheme method for adding a new element.
/// TODO: remove dim2lvl
#define DECL_ADDELT(VNAME, V) \
MLIR_CRUNNERUTILS_EXPORT void *_mlir_ciface_addElt##VNAME( \
void *lvlCOO, StridedMemRefType<V, 0> *vref, \
StridedMemRefType<index_type, 1> *dimCoordsRef, \
StridedMemRefType<index_type, 1> *dim2lvlRef);
MLIR_SPARSETENSOR_FOREVERY_V(DECL_ADDELT)
#undef DECL_ADDELT
/// Tensor-storage method for a dim to lvl forwarding insertion.
#define DECL_FORWARDINGINSERT(VNAME, V) \
MLIR_CRUNNERUTILS_EXPORT void _mlir_ciface_forwardingInsert##VNAME( \
void *tensor, StridedMemRefType<V, 0> *vref, \
StridedMemRefType<index_type, 1> *dimCoordsRef); \
MLIR_SPARSETENSOR_FOREVERY_V(DECL_FORWARDINGINSERT)
#undef DECL_FORWARDINGINSERT

/// Coordinate-scheme method for getting the next element while iterating.
/// The `cref` argument uses the same coordinate-space as the `iter` (which
/// can be either dim- or lvl-coords, depending on context).
#define DECL_GETNEXT(VNAME, V) \
MLIR_CRUNNERUTILS_EXPORT bool _mlir_ciface_getNext##VNAME( \
void *iter, StridedMemRefType<index_type, 1> *cref, \
Expand Down Expand Up @@ -185,8 +179,11 @@ MLIR_CRUNNERUTILS_EXPORT index_type sparseLvlSize(void *tensor, index_type l);
/// Tensor-storage method to get the size of the given dimension.
MLIR_CRUNNERUTILS_EXPORT index_type sparseDimSize(void *tensor, index_type d);

/// Tensor-storage method to finalize forwarding insertions.
MLIR_CRUNNERUTILS_EXPORT void endForwardingInsert(void *tensor);

/// Tensor-storage method to finalize lexicographic insertions.
MLIR_CRUNNERUTILS_EXPORT void endInsert(void *tensor);
MLIR_CRUNNERUTILS_EXPORT void endLexInsert(void *tensor);

/// Coordinate-scheme method to write to file in extended FROSTT format.
#define DECL_OUTSPARSETENSOR(VNAME, V) \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -596,7 +596,7 @@ class SparseTensorLoadConverter : public OpConversionPattern<LoadOp> {
ConversionPatternRewriter &rewriter) const override {
if (op.getHasInserts()) {
// Finalize any pending insertions.
StringRef name = "endInsert";
StringRef name = "endLexInsert";
createFuncCall(rewriter, op->getLoc(), name, {}, adaptor.getOperands(),
EmitCInterface::Off);
}
Expand Down
7 changes: 7 additions & 0 deletions mlir/lib/ExecutionEngine/SparseTensor/Storage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,13 @@ MLIR_SPARSETENSOR_FOREVERY_FIXED_O(IMPL_GETCOORDINATES)
MLIR_SPARSETENSOR_FOREVERY_V(IMPL_GETVALUES)
#undef IMPL_GETVALUES

#define IMPL_FORWARDINGINSERT(VNAME, V) \
void SparseTensorStorageBase::forwardingInsert(const uint64_t *, V) { \
FATAL_PIV("forwardingInsert" #VNAME); \
}
MLIR_SPARSETENSOR_FOREVERY_V(IMPL_FORWARDINGINSERT)
#undef IMPL_FORWARDINGINSERT

#define IMPL_LEXINSERT(VNAME, V) \
void SparseTensorStorageBase::lexInsert(const uint64_t *, V) { \
FATAL_PIV("lexInsert" #VNAME); \
Expand Down
55 changes: 29 additions & 26 deletions mlir/lib/ExecutionEngine/SparseTensorRuntime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,9 +177,16 @@ extern "C" {
#define CASE(p, c, v, P, C, V) \
if (posTp == (p) && crdTp == (c) && valTp == (v)) { \
switch (action) { \
case Action::kEmpty: \
case Action::kEmpty: { \
return SparseTensorStorage<P, C, V>::newEmpty( \
dimRank, dimSizes, lvlRank, lvlSizes, lvlTypes, dim2lvl, lvl2dim); \
dimRank, dimSizes, lvlRank, lvlSizes, lvlTypes, dim2lvl, lvl2dim, \
false); \
} \
case Action::kEmptyForward: { \
return SparseTensorStorage<P, C, V>::newEmpty( \
dimRank, dimSizes, lvlRank, lvlSizes, lvlTypes, dim2lvl, lvl2dim, \
true); \
} \
case Action::kFromCOO: { \
assert(ptr && "Received nullptr for SparseTensorCOO object"); \
auto &coo = *static_cast<SparseTensorCOO<V> *>(ptr); \
Expand All @@ -193,8 +200,9 @@ extern "C" {
dimRank, dimSizes, lvlRank, lvlSizes, lvlTypes, dim2lvl, lvl2dim, \
dimRank, tensor); \
} \
case Action::kEmptyCOO: \
return new SparseTensorCOO<V>(lvlRank, lvlSizes); \
case Action::kFuture: { \
break; \
} \
case Action::kToCOO: { \
assert(ptr && "Received nullptr for SparseTensorStorage object"); \
auto &tensor = *static_cast<SparseTensorStorage<P, C, V> *>(ptr); \
Expand Down Expand Up @@ -405,29 +413,20 @@ MLIR_SPARSETENSOR_FOREVERY_O(IMPL_SPARSECOORDINATES)
#undef IMPL_SPARSECOORDINATES
#undef IMPL_GETOVERHEAD

// TODO: use MapRef here for translation of coordinates
// TODO: remove dim2lvl
#define IMPL_ADDELT(VNAME, V) \
void *_mlir_ciface_addElt##VNAME( \
void *lvlCOO, StridedMemRefType<V, 0> *vref, \
StridedMemRefType<index_type, 1> *dimCoordsRef, \
StridedMemRefType<index_type, 1> *dim2lvlRef) { \
assert(lvlCOO &&vref); \
#define IMPL_FORWARDINGINSERT(VNAME, V) \
void _mlir_ciface_forwardingInsert##VNAME( \
void *t, StridedMemRefType<V, 0> *vref, \
StridedMemRefType<index_type, 1> *dimCoordsRef) { \
assert(t &&vref); \
ASSERT_NO_STRIDE(dimCoordsRef); \
ASSERT_NO_STRIDE(dim2lvlRef); \
const uint64_t rank = MEMREF_GET_USIZE(dimCoordsRef); \
ASSERT_USIZE_EQ(dim2lvlRef, rank); \
const index_type *dimCoords = MEMREF_GET_PAYLOAD(dimCoordsRef); \
const index_type *dim2lvl = MEMREF_GET_PAYLOAD(dim2lvlRef); \
std::vector<index_type> lvlCoords(rank); \
for (uint64_t d = 0; d < rank; ++d) \
lvlCoords[dim2lvl[d]] = dimCoords[d]; \
V *value = MEMREF_GET_PAYLOAD(vref); \
static_cast<SparseTensorCOO<V> *>(lvlCOO)->add(lvlCoords, *value); \
return lvlCOO; \
assert(dimCoords); \
const V *value = MEMREF_GET_PAYLOAD(vref); \
static_cast<SparseTensorStorageBase *>(t)->forwardingInsert(dimCoords, \
*value); \
}
MLIR_SPARSETENSOR_FOREVERY_V(IMPL_ADDELT)
#undef IMPL_ADDELT
MLIR_SPARSETENSOR_FOREVERY_V(IMPL_FORWARDINGINSERT)
#undef IMPL_FORWARDINGINSERT

// NOTE: the `cref` argument uses the same coordinate-space as the `iter`
// (which can be either dim- or lvl-coords, depending on context).
Expand Down Expand Up @@ -692,8 +691,12 @@ index_type sparseDimSize(void *tensor, index_type d) {
return static_cast<SparseTensorStorageBase *>(tensor)->getDimSize(d);
}

void endInsert(void *tensor) {
return static_cast<SparseTensorStorageBase *>(tensor)->endInsert();
void endForwardingInsert(void *tensor) {
return static_cast<SparseTensorStorageBase *>(tensor)->endForwardingInsert();
}

void endLexInsert(void *tensor) {
return static_cast<SparseTensorStorageBase *>(tensor)->endLexInsert();
}

#define IMPL_OUTSPARSETENSOR(VNAME, V) \
Expand Down
2 changes: 1 addition & 1 deletion mlir/test/Dialect/SparseTensor/conversion.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ func.func @sparse_reconstruct(%arg0: tensor<128xf32, #SparseVector>) -> tensor<1

// CHECK-LABEL: func @sparse_reconstruct_ins(
// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8>
// CHECK: call @endInsert(%[[A]]) : (!llvm.ptr<i8>) -> ()
// CHECK: call @endLexInsert(%[[A]]) : (!llvm.ptr<i8>) -> ()
// CHECK: return %[[A]] : !llvm.ptr<i8>
func.func @sparse_reconstruct_ins(%arg0: tensor<128xf32, #SparseVector>) -> tensor<128xf32, #SparseVector> {
%0 = sparse_tensor.load %arg0 hasInserts : tensor<128xf32, #SparseVector>
Expand Down
6 changes: 3 additions & 3 deletions mlir/test/Dialect/SparseTensor/sparse_expand.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
// CHECK-CONVERT: memref.dealloc %[[A]] : memref<?xf64>
// CHECK-CONVERT: memref.dealloc %[[B]] : memref<?xi1>
// CHECK-CONVERT: memref.dealloc %[[C]] : memref<?xindex>
// CHECK-CONVERT: call @endInsert
// CHECK-CONVERT: call @endLexInsert
//
func.func @kernel(%arga: tensor<?x?xf64, #DCSC>) -> tensor<?xf64, #SV> {
%c0 = arith.constant 0 : index
Expand Down Expand Up @@ -115,7 +115,7 @@ func.func @kernel(%arga: tensor<?x?xf64, #DCSC>) -> tensor<?xf64, #SV> {
// CHECK-CONVERT: memref.dealloc %[[A]] : memref<?xf64>
// CHECK-CONVERT: memref.dealloc %[[B]] : memref<?xi1>
// CHECK-CONVERT: memref.dealloc %[[C]] : memref<?xindex>
// CHECK-CONVERT: call @endInsert
// CHECK-CONVERT: call @endLexInsert
//
func.func @matmul1(%A: tensor<8x2xf64, #CSR>,
%B: tensor<2x4xf64, #CSR>) -> tensor<8x4xf64, #CSR> {
Expand Down Expand Up @@ -163,7 +163,7 @@ func.func @matmul1(%A: tensor<8x2xf64, #CSR>,
// CHECK-CONVERT: memref.dealloc %[[A]] : memref<?xf64>
// CHECK-CONVERT: memref.dealloc %[[B]] : memref<?xi1>
// CHECK-CONVERT: memref.dealloc %[[C]] : memref<?xindex>
// CHECK-CONVERT: call @endInsert
// CHECK-CONVERT: call @endLexInsert
//
func.func @matmul2(%A: tensor<8x2xf64, #CSC>,
%B: tensor<2x4xf64, #CSC>) -> tensor<8x4xf64, #CSC> {
Expand Down
2 changes: 1 addition & 1 deletion mlir/test/Dialect/SparseTensor/sparse_fill_zero.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@
// CHECK: memref.dealloc %[[VAL_20]] : memref<300xf64>
// CHECK: memref.dealloc %[[VAL_22]] : memref<300xi1>
// CHECK: memref.dealloc %[[VAL_24]] : memref<300xindex>
// CHECK: call @endInsert(%[[VAL_19]]) : (!llvm.ptr<i8>) -> ()
// CHECK: call @endLexInsert(%[[VAL_19]]) : (!llvm.ptr<i8>) -> ()
// CHECK: return %[[VAL_19]] : !llvm.ptr<i8>
// CHECK: }
func.func @fill_zero_after_alloc(%arg0: tensor<100x200xf64, #DCSR>,
Expand Down