[Mlir-commits] [mlir] [mlir][sparse] deprecate the convert{To, From}MLIRSparseTensor methods (PR #66304)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Wed Sep 13 16:22:46 PDT 2023


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-mlir-execution-engine
            
<details>
<summary>Changes</summary>
Rationale:
These libraries provided COO input and output at external boundaries which, since then, has been generalized to the much more powerful pack and unpack operations of the sparse tensor dialect.
--
Full diff: https://github.com/llvm/llvm-project/pull/66304.diff

3 Files Affected:

- (modified) mlir/include/mlir/ExecutionEngine/SparseTensor/Storage.h (-16) 
- (modified) mlir/include/mlir/ExecutionEngine/SparseTensorRuntime.h (+3-52) 
- (modified) mlir/lib/ExecutionEngine/SparseTensorRuntime.cpp (-129) 


<pre>
diff --git a/mlir/include/mlir/ExecutionEngine/SparseTensor/Storage.h b/mlir/include/mlir/ExecutionEngine/SparseTensor/Storage.h
index baf88f3a335c26e..68dcab6e64c7e45 100644
--- a/mlir/include/mlir/ExecutionEngine/SparseTensor/Storage.h
+++ b/mlir/include/mlir/ExecutionEngine/SparseTensor/Storage.h
@@ -88,8 +88,6 @@ class PermutationRef final {
     return out;
   }
 
-  // NOTE: This form of the method is required by `toMLIRSparseTensor`,
-  // so it can reuse the `out` buffer for each iteration of a loop.
   template <typename T>
   inline void pushforward(uint64_t size, const T *values, T *out) const {
     assert(size == permSize && "size mismatch");
@@ -97,20 +95,6 @@ class PermutationRef final {
       out[perm[i]] = values[i];
   }
 
-  // NOTE: this is only needed by `toMLIRSparseTensor`, which in
-  // turn only needs it as a vector to hand off to `newSparseTensor`.
-  // Otherwise we would want the result to be an owning-permutation,
-  // to retain the knowledge that `isPermutation` is true.
-  //
-  /// Constructs the inverse permutation.  This is equivalent to calling
-  /// `pushforward` with `std::iota` for the values.
-  inline std::vector<uint64_t> inverse() const {
-    std::vector<uint64_t> out(permSize);
-    for (uint64_t i = 0; i < permSize; ++i)
-      out[perm[i]] = i;
-    return out;
-  }
-
   /// Constructs a permuted array of values.  This method is the inverse
   /// of `pushforward` in the sense that for all `p` and `xs` we have:
   /// * `p.permute(p.pushforward(xs)) == xs`
diff --git a/mlir/include/mlir/ExecutionEngine/SparseTensorRuntime.h b/mlir/include/mlir/ExecutionEngine/SparseTensorRuntime.h
index fc0d4a27b0787b8..14f89bee05bf550 100644
--- a/mlir/include/mlir/ExecutionEngine/SparseTensorRuntime.h
+++ b/mlir/include/mlir/ExecutionEngine/SparseTensorRuntime.h
@@ -227,54 +227,6 @@ MLIR_CRUNNERUTILS_EXPORT char *getTensorFilename(index_type id);
 MLIR_CRUNNERUTILS_EXPORT void readSparseTensorShape(char *filename,
                                                     std::vector<uint64_t> *out);
 
-/// Initializes sparse tensor from a COO-flavored format expressed using
-/// C-style data structures.  The expected parameters are:
-///
-///   rank:    rank of tensor
-///   nse:     number of specified elements (usually the nonzeros)
-///   shape:   array with dimension size for each rank
-///   values:  a "nse" array with values for all specified elements
-///   coordinates: a flat "nse * rank" array with coordinates for all
-///            specified elements
-///   perm:    the permutation of the levels in the storage
-///   sparse:  the sparsity for the levels
-///
-/// For example, the sparse matrix
-///     | 1.0 0.0 0.0 |
-///     | 0.0 5.0 3.0 |
-/// can be passed as
-///      rank    = 2
-///      nse     = 3
-///      shape   = [2, 3]
-///      values  = [1.0, 5.0, 3.0]
-///      coordinates = [ 0, 0,  1, 1,  1, 2]
-#define DECL_CONVERTTOMLIRSPARSETENSOR(VNAME, V)                               \
-  MLIR_CRUNNERUTILS_EXPORT void *convertToMLIRSparseTensor##VNAME(             \
-      uint64_t rank, uint64_t nse, uint64_t *dimSizes, V *values,              \
-      uint64_t *dimCoordinates, uint64_t *dim2lvl, uint8_t *lvlTypes);
-MLIR_SPARSETENSOR_FOREVERY_V(DECL_CONVERTTOMLIRSPARSETENSOR)
-#undef DECL_CONVERTTOMLIRSPARSETENSOR
-
-/// Converts a sparse tensor to COO-flavored format expressed using
-/// C-style data structures.  The expected output parameters are pointers
-/// for these values:
-///
-///   rank:    rank of tensor
-///   nse:     number of specified elements (usually the nonzeros)
-///   shape:   array with size for each dimension
-///   values:  a "nse" array with values for all specified elements
-///   coordinates: a flat "nse * rank" array with coordinates for all
-///            specified elements
-///
-/// The input is a pointer to `SparseTensorStorage<P, C, V>`, typically
-/// returned from `convertToMLIRSparseTensor`.
-#define DECL_CONVERTFROMMLIRSPARSETENSOR(VNAME, V)                             \
-  MLIR_CRUNNERUTILS_EXPORT void convertFromMLIRSparseTensor##VNAME(            \
-      void *tensor, uint64_t *pRank, uint64_t *pNse, uint64_t **pShape,        \
-      V **pValues, uint64_t **pCoordinates);
-MLIR_SPARSETENSOR_FOREVERY_V(DECL_CONVERTFROMMLIRSPARSETENSOR)
-#undef DECL_CONVERTFROMMLIRSPARSETENSOR
-
 /// Returns the rank of the sparse tensor being read.
 MLIR_CRUNNERUTILS_EXPORT index_type getSparseTensorReaderRank(void *p);
 
@@ -292,10 +244,9 @@ MLIR_CRUNNERUTILS_EXPORT index_type getSparseTensorReaderDimSize(void *p,
 /// the reader.
 MLIR_CRUNNERUTILS_EXPORT void delSparseTensorReader(void *p);
 
-/// Creates a SparseTensorWriter for outputing a sparse tensor to a file with
-/// the given file name. When the file name is empty, std::cout is used.
-//
-// Only the extended FROSTT format is supported currently.
+/// Creates a SparseTensorWriter for outputting a sparse tensor to a file
+/// with the given file name. When the file name is empty, std::cout is used.
+/// Only the extended FROSTT format is supported currently.
 MLIR_CRUNNERUTILS_EXPORT void *createSparseTensorWriter(char *filename);
 
 /// Finalizes the outputing of a sparse tensor to a file and releases the
diff --git a/mlir/lib/ExecutionEngine/SparseTensorRuntime.cpp b/mlir/lib/ExecutionEngine/SparseTensorRuntime.cpp
index d76a34564c47a42..82cb6d3aeefa35f 100644
--- a/mlir/lib/ExecutionEngine/SparseTensorRuntime.cpp
+++ b/mlir/lib/ExecutionEngine/SparseTensorRuntime.cpp
@@ -108,112 +108,6 @@ class SparseTensorIterator final {
   const typename SparseTensorCOO<V>::const_iterator end;
 };
 
-// TODO: When using this library from MLIR, the `toMLIRSparseTensor`/
-// `IMPL_CONVERTTOMLIRSPARSETENSOR` and `fromMLIRSparseTensor`/
-// `IMPL_CONVERTFROMMLIRSPARSETENSOR` constructs will be codegened away;
-// therefore, these functions are only used by PyTACO, one place in the
-// Python integration tests, and possibly by out-of-tree projects.
-// This is notable because neither function can be easily generalized
-// to handle non-permutations.  In particular, while we could adjust
-// the functions to take all the arguments they&#x27;d need, that would just
-// push the problem into client code.  So if we want to generalize these
-// functions to support non-permutations, we&#x27;ll need to figure out how
-// to do so without putting undue burden on clients.
-
-/// Initializes sparse tensor from an external COO-flavored format.
-/// The `rank` argument is both dimension-rank and level-rank, and the
-/// `dim2lvl` argument must be a permutation.
-/// Used by `IMPL_CONVERTTOMLIRSPARSETENSOR`.
-//
-// TODO: generalize beyond 64-bit overhead types.
-template <typename V>
-static SparseTensorStorage<uint64_t, uint64_t, V> *
-toMLIRSparseTensor(uint64_t rank, uint64_t nse, const uint64_t *dimSizes,
-                   const V *values, const uint64_t *dimCoordinates,
-                   const uint64_t *dim2lvl, const DimLevelType *lvlTypes) {
-#ifndef NDEBUG
-  // Verify that the sparsity values are supported.
-  // TODO: update this check to match what we actually support.
-  for (uint64_t i = 0; i < rank; ++i)
-    if (lvlTypes[i] != DimLevelType::Dense &&
-        lvlTypes[i] != DimLevelType::Compressed)
-      MLIR_SPARSETENSOR_FATAL("unsupported level type: %d\n",
-                              static_cast<uint8_t>(lvlTypes[i]));
-#endif
-  // Verify that `dim2lvl` is a permutation of `[0..(rank-1)]`.
-  // NOTE: The construction of `lvlSizes` and `lvl2dim` don&#x27;t generalize
-  // to arbitrary `dim2lvl` mappings.  Whereas constructing `lvlCoords` from
-  // `dimCoords` does (though the details would have to be updated, just
-  // like for `IMPL_ADDELT`).
-  const detail::PermutationRef d2l(rank, dim2lvl);
-  // Convert external format to internal COO.
-  const auto lvlSizes = d2l.pushforward(rank, dimSizes);
-  auto *lvlCOO = new SparseTensorCOO<V>(lvlSizes, nse);
-  std::vector<uint64_t> lvlCoords(rank);
-  const uint64_t *dimCoords = dimCoordinates;
-  for (uint64_t i = 0; i < nse; ++i) {
-    d2l.pushforward(rank, dimCoords, lvlCoords.data());
-    lvlCOO->add(lvlCoords, values[i]);
-    dimCoords += rank;
-  }
-  // Return sparse tensor storage format as opaque pointer.
-  const auto lvl2dim = d2l.inverse();
-  auto *tensor = SparseTensorStorage<uint64_t, uint64_t, V>::newFromCOO(
-      rank, dimSizes, rank, lvlTypes, lvl2dim.data(), *lvlCOO);
-  delete lvlCOO;
-  return tensor;
-}
-
-/// Converts a sparse tensor to an external COO-flavored format.
-/// Used by `IMPL_CONVERTFROMMLIRSPARSETENSOR`.
-//
-// TODO: Currently, values are copied from SparseTensorStorage to
-// SparseTensorCOO, then to the output.  We may want to reduce the number
-// of copies.
-//
-// TODO: generalize beyond 64-bit overhead types, no dim ordering,
-// all dimensions compressed
-template <typename V>
-static void
-fromMLIRSparseTensor(const SparseTensorStorage<uint64_t, uint64_t, V> *tensor,
-                     uint64_t *pRank, uint64_t *pNse, uint64_t **pShape,
-                     V **pValues, uint64_t **pCoordinates) {
-  assert(tensor && "Received nullptr for tensor");
-  const uint64_t dimRank = tensor->getDimRank();
-  const auto &dimSizes = tensor->getDimSizes();
-  std::vector<uint64_t> identityPerm(dimRank);
-  std::iota(identityPerm.begin(), identityPerm.end(), 0);
-  SparseTensorCOO<V> *coo =
-      tensor->toCOO(dimRank, dimSizes.data(), dimRank, identityPerm.data());
-
-  const std::vector<Element<V>> &elements = coo->getElements();
-  const uint64_t nse = elements.size();
-
-  const auto &cooSizes = coo->getDimSizes();
-  assert(cooSizes.size() == dimRank && "Rank mismatch");
-  uint64_t *dimShape = new uint64_t[dimRank];
-  std::memcpy(static_cast<void *>(dimShape),
-              static_cast<const void *>(cooSizes.data()),
-              sizeof(uint64_t) * dimRank);
-
-  V *values = new V[nse];
-  uint64_t *coordinates = new uint64_t[dimRank * nse];
-
-  for (uint64_t i = 0, base = 0; i < nse; ++i) {
-    values[i] = elements[i].value;
-    for (uint64_t d = 0; d < dimRank; ++d)
-      coordinates[base + d] = elements[i].coords[d];
-    base += dimRank;
-  }
-
-  delete coo;
-  *pRank = dimRank;
-  *pNse = nse;
-  *pShape = dimShape;
-  *pValues = values;
-  *pCoordinates = coordinates;
-}
-
 //===----------------------------------------------------------------------===//
 //
 // Utilities for manipulating `StridedMemRefType`.
@@ -863,29 +757,6 @@ void readSparseTensorShape(char *filename, std::vector<uint64_t> *out) {
   out->assign(dimSizes, dimSizes + dimRank);
 }
 
-// We can&#x27;t use `static_cast` here because `DimLevelType` is an enum-class.
-#define IMPL_CONVERTTOMLIRSPARSETENSOR(VNAME, V)                               \
-  void *convertToMLIRSparseTensor##VNAME(                                      \
-      uint64_t rank, uint64_t nse, uint64_t *dimSizes, V *values,              \
-      uint64_t *dimCoordinates, uint64_t *dim2lvl, uint8_t *lvlTypes) {        \
-    return toMLIRSparseTensor<V>(rank, nse, dimSizes, values, dimCoordinates,  \
-                                 dim2lvl,                                      \
-                                 reinterpret_cast<DimLevelType *>(lvlTypes));  \
-  }
-MLIR_SPARSETENSOR_FOREVERY_V(IMPL_CONVERTTOMLIRSPARSETENSOR)
-#undef IMPL_CONVERTTOMLIRSPARSETENSOR
-
-#define IMPL_CONVERTFROMMLIRSPARSETENSOR(VNAME, V)                             \
-  void convertFromMLIRSparseTensor##VNAME(                                     \
-      void *tensor, uint64_t *pRank, uint64_t *pNse, uint64_t **pShape,        \
-      V **pValues, uint64_t **pCoordinates) {                                  \
-    fromMLIRSparseTensor<V>(                                                   \
-        static_cast<SparseTensorStorage<uint64_t, uint64_t, V> *>(tensor),     \
-        pRank, pNse, pShape, pValues, pCoordinates);                           \
-  }
-MLIR_SPARSETENSOR_FOREVERY_V(IMPL_CONVERTFROMMLIRSPARSETENSOR)
-#undef IMPL_CONVERTFROMMLIRSPARSETENSOR
-
 index_type getSparseTensorReaderRank(void *p) {
   return static_cast<SparseTensorReader *>(p)->getRank();
 }
</pre>
</details>


https://github.com/llvm/llvm-project/pull/66304


More information about the Mlir-commits mailing list