MLIR 22.0.0git
SparseTensorStorageLayout.h
Go to the documentation of this file.
1//===- SparseTensorStorageLayout.h ------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This header file defines utilities for the sparse memory layout.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef MLIR_DIALECT_SPARSETENSOR_IR_SPARSETENSORSTORAGELAYOUT_H_
14#define MLIR_DIALECT_SPARSETENSOR_IR_SPARSETENSORSTORAGELAYOUT_H_
15
18
19namespace mlir {
20namespace sparse_tensor {
21
22///===----------------------------------------------------------------------===//
23/// The sparse tensor storage scheme for a tensor is organized as a single
24/// compound type with the following fields. Note that every memref with `?`
25/// size actually behaves as a "vector", i.e. the stored size is the capacity
26/// and the used size resides in the storage_specifier struct.
27///
28/// struct {
29/// ; per-level l:
30/// ; if dense:
31/// <nothing>
32/// ; if compressed:
33/// memref<[batch] x ? x pos> positions ; positions for level l
34/// memref<[batch] x ? x crd> coordinates ; coordinates for level l
35/// ; if loose-[batch] x compressed:
36/// memref<[batch] x ? x pos> positions ; lo/hi pos pairs for level l
37/// memref<[batch] x ? x crd> coordinates ; coordinates for level l
38/// ; if singleton/2-out-of-4:
39/// memref<[batch] x ? x crd> coordinates ; coordinates for level l
40///
41/// memref<[batch] x ? x eltType> values ; values
42///
43/// struct sparse_tensor.storage_specifier {
44/// array<rank x int> lvlSizes ; sizes/cardinalities for each level
45/// // TODO: memSizes need to be expanded to array<[batch] x n x int> to
46/// // support different sizes for different batches. At the moment, we
47/// // assume that every batch occupies the same memory size.
48/// array<n x int> memSizes ; sizes/lengths for each data memref
49/// }
50/// };
51///
52/// In addition, for a "trailing COO region", defined as a compressed level
53/// followed by one or more singleton levels, the default SOA storage that
54/// is inherent to the TACO format is optimized into an AOS storage where
55/// all coordinates of a stored element appear consecutively. In such cases,
56/// a special operation (sparse_tensor.coordinates_buffer) must be used to
57/// access the AOS coordinates array. In the code below, the method
58/// `getCOOStart` is used to find the start of the "trailing COO region".
59///
60/// If the sparse tensor is a slice (produced by `tensor.extract_slice`
61/// operation), instead of allocating a new sparse tensor for it, it reuses the
62/// same sets of MemRefs but attaching a additional set of slicing-metadata for
63/// per-dimension slice offset and stride.
64///
65/// Examples.
66///
67/// #CSR storage of 2-dim matrix yields
68/// memref<?xindex> ; positions-1
69/// memref<?xindex> ; coordinates-1
70/// memref<?xf64> ; values
71/// struct<(array<2 x i64>, array<3 x i64>)>) ; lvl0, lvl1, 3xsizes
72///
73/// #COO storage of 2-dim matrix yields
74/// memref<?xindex>, ; positions-0, essentially [0,sz]
75/// memref<?xindex> ; AOS coordinates storage
76/// memref<?xf64> ; values
77/// struct<(array<2 x i64>, array<3 x i64>)>) ; lvl0, lvl1, 3xsizes
78///
79/// Slice on #COO storage of 2-dim matrix yields
80/// ;; Inherited from the original sparse tensors
81/// memref<?xindex>, ; positions-0, essentially [0,sz]
82/// memref<?xindex> ; AOS coordinates storage
83/// memref<?xf64> ; values
84/// struct<(array<2 x i64>, array<3 x i64>, ; lvl0, lvl1, 3xsizes
85/// ;; Extra slicing-metadata
86/// array<2 x i64>, array<2 x i64>)>) ; dim offset, dim stride.
87///
88///===----------------------------------------------------------------------===//
89
90enum class SparseTensorFieldKind : uint32_t {
92 PosMemRef = static_cast<uint32_t>(StorageSpecifierKind::PosMemSize),
93 CrdMemRef = static_cast<uint32_t>(StorageSpecifierKind::CrdMemSize),
94 ValMemRef = static_cast<uint32_t>(StorageSpecifierKind::ValMemSize)
95};
96
97inline StorageSpecifierKind toSpecifierKind(SparseTensorFieldKind kind) {
99 return static_cast<StorageSpecifierKind>(kind);
100}
101
102inline SparseTensorFieldKind toFieldKind(StorageSpecifierKind kind) {
103 assert(kind != StorageSpecifierKind::LvlSize);
104 return static_cast<SparseTensorFieldKind>(kind);
105}
106
107/// The type of field indices. This alias is to help code be more
108/// self-documenting; unfortunately it is not type-checked, so it only
109/// provides documentation rather than doing anything to prevent mixups.
111
112/// Provides methods to access fields of a sparse tensor with the given
113/// encoding.
115public:
116 explicit StorageLayout(const SparseTensorType &stt)
117 : StorageLayout(stt.getEncoding()) {}
118 explicit StorageLayout(SparseTensorEncodingAttr enc) : enc(enc) {
119 assert(enc);
120 }
121
122 /// For each field that will be allocated for the given sparse tensor
123 /// encoding, calls the callback with the corresponding field index,
124 /// field kind, level, and level-type (the last two are only for level
125 /// memrefs). The field index always starts with zero and increments
126 /// by one between each callback invocation. Ideally, all other methods
127 /// should rely on this function to query a sparse tensor fields instead
128 /// of relying on ad-hoc index computation.
129 void foreachField(
131 FieldIndex /*fieldIdx*/, SparseTensorFieldKind /*fieldKind*/,
132 Level /*lvl (if applicable)*/, LevelType /*LT (if applicable)*/)>)
133 const;
134
135 /// Gets the field index for required field.
137 std::optional<Level> lvl) const {
138 return getFieldIndexAndStride(kind, lvl).first;
139 }
140
141 /// Gets the total number of fields for the given sparse tensor encoding.
142 unsigned getNumFields() const;
143
144 /// Gets the total number of data fields (coordinate arrays, position
145 /// arrays, and a value array) for the given sparse tensor encoding.
146 unsigned getNumDataFields() const;
147
148 std::pair<FieldIndex, unsigned>
150 std::optional<Level> lvl) const;
151
152private:
153 const SparseTensorEncodingAttr enc;
154};
155
156//
157// Wrapper functions to invoke StorageLayout-related method.
158//
159
160inline unsigned getNumFieldsFromEncoding(SparseTensorEncodingAttr enc) {
161 return StorageLayout(enc).getNumFields();
162}
163
164inline unsigned getNumDataFieldsFromEncoding(SparseTensorEncodingAttr enc) {
165 return StorageLayout(enc).getNumDataFields();
166}
167
169 SparseTensorEncodingAttr enc,
171 LevelType)>
172 callback) {
173 return StorageLayout(enc).foreachField(callback);
174}
175
177 SparseTensorType,
179 LevelType)>);
180
181} // namespace sparse_tensor
182} // namespace mlir
183
184#endif // MLIR_DIALECT_SPARSETENSOR_IR_SPARSETENSORSTORAGELAYOUT_H_
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition Types.h:74
A wrapper around RankedTensorType, which has three goals:
Provides methods to access fields of a sparse tensor with the given encoding.
unsigned getNumDataFields() const
Gets the total number of data fields (coordinate arrays, position arrays, and a value array) for the ...
unsigned getNumFields() const
Gets the total number of fields for the given sparse tensor encoding.
StorageLayout(SparseTensorEncodingAttr enc)
FieldIndex getMemRefFieldIndex(SparseTensorFieldKind kind, std::optional< Level > lvl) const
Gets the field index for required field.
void foreachField(llvm::function_ref< bool(FieldIndex, SparseTensorFieldKind, Level, LevelType)>) const
For each field that will be allocated for the given sparse tensor encoding, calls the callback with t...
std::pair< FieldIndex, unsigned > getFieldIndexAndStride(SparseTensorFieldKind kind, std::optional< Level > lvl) const
void foreachFieldAndTypeInSparseTensor(SparseTensorType, llvm::function_ref< bool(Type, FieldIndex, SparseTensorFieldKind, Level, LevelType)>)
unsigned FieldIndex
The type of field indices.
uint64_t Level
The type of level identifiers and level-ranks.
SparseTensorFieldKind toFieldKind(StorageSpecifierKind kind)
unsigned getNumDataFieldsFromEncoding(SparseTensorEncodingAttr enc)
unsigned getNumFieldsFromEncoding(SparseTensorEncodingAttr enc)
SparseTensorFieldKind
===-------------------------------------------------------------------—===// The sparse tensor storag...
StorageSpecifierKind toSpecifierKind(SparseTensorFieldKind kind)
void foreachFieldInSparseTensor(SparseTensorEncodingAttr enc, llvm::function_ref< bool(FieldIndex, SparseTensorFieldKind, Level, LevelType)> callback)
Include the generated interface declarations.
This enum defines all the sparse representations supportable by the SparseTensor dialect.
Definition Enums.h:238