Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
46f4fc0
docs: design TensorView inline metadata storage
voltjia Jul 23, 2026
c4bd1ea
docs: plan TensorView inline metadata
voltjia Jul 23, 2026
ce6c947
perf: expand TensorView metadata benchmarks
voltjia Jul 23, 2026
f0ae325
test: specify SmallVector behavior
voltjia Jul 23, 2026
9a74589
feat: add inline SmallVector storage
voltjia Jul 23, 2026
425357d
test: define TensorView inline metadata behavior
voltjia Jul 23, 2026
b5f4602
perf: inline TensorView metadata
voltjia Jul 23, 2026
61b6b66
test: define eight-dimension inline boundary
voltjia Jul 24, 2026
6af993d
perf: evaluate eight inline dimensions
voltjia Jul 24, 2026
b2864ec
test: cover all inline TensorView ranks
voltjia Jul 24, 2026
034b7d4
test: define combined TensorView metadata behavior
voltjia Jul 24, 2026
94841f4
perf: combine TensorView metadata storage
voltjia Jul 24, 2026
31d621d
test: define eight-dimension combined metadata boundary
voltjia Jul 24, 2026
a8f4530
perf: evaluate eight combined metadata dimensions
voltjia Jul 24, 2026
309bd7e
fix: enforce tensor metadata size preconditions
voltjia Jul 24, 2026
8ba2501
perf: select capacity-eight TensorView metadata
voltjia Jul 25, 2026
d113995
fix: preserve Tensor metadata fill construction
voltjia Jul 27, 2026
b5f5154
style: format TensorView changes
voltjia Jul 27, 2026
2d94f2e
chore: exclude development process documents
voltjia Jul 28, 2026
4cdfb51
refactor: clarify shape and strides storage naming
voltjia Jul 28, 2026
181474c
perf: inline TensorView metadata accessors
voltjia Jul 29, 2026
425c770
style: align metadata code with conventions
voltjia Aug 4, 2026
3a4bb7a
refactor: share benchmark noinline macro
voltjia Aug 4, 2026
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
13 changes: 11 additions & 2 deletions docs/api/core-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ floating point, and standard floating point types:

## TensorView

`infini::rt::TensorView` is a non-owning description of tensor memory.
`infini::rt::TensorView` is a non-owning description of tensor memory that owns
its shape and stride metadata.

```cpp
std::vector<float> data(16);
Expand All @@ -66,4 +67,12 @@ auto contiguous = tensor.IsContiguous();
- device
- strides

It does not own the memory it references.
It does not own the tensor data it references. Shape and strides are stored
inline for ranks 0 through 8; rank 9 and above use owned heap fallback storage.
Construction from `std::vector` and other compatible contiguous ranges remains
supported.

On an lvalue `TensorView`, `shape()` and `strides()` return lightweight
contiguous views by value. Those views borrow metadata from the `TensorView` and
must not outlive it. Calling the accessors on an rvalue returns owning metadata
so a view cannot dangle from a temporary.
14 changes: 14 additions & 0 deletions docs/compatibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,17 @@ by the same configured build.
InfiniRT currently exposes a C++ API. Consumers should treat the installed
headers and `libinfinirt.so` as a matching pair from the same build or release.

`TensorView::Shape` and `TensorView::Strides` are concrete vector-like C++
aliases using inline capacity 8. `TensorView` stores ranks 0 through 8 inline
and uses owned heap fallback at rank 9 and above. This representation changes
`TensorView` layout and is an API/ABI compatibility break from the previous
`std::vector` aliases. Consumers must rebuild after this alias or layout change
and must not mix headers and libraries from different builds.

Existing construction from `std::vector` remains supported, but code that
requires the exact `std::vector` alias must adapt. On lvalues, `shape()` and
`strides()` now return typed borrowed contiguous views by value; callers that
need ownership should explicitly materialize `TensorView::Shape` or
`TensorView::Strides`. The owning aliases support the common
`Strides(count, value)` construction used by downstream metadata code.

1 change: 1 addition & 0 deletions scripts/run_performance_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ def main():
"perf_runtime_dispatch",
"perf_memory",
"perf_tensor_view",
"perf_tensor_view_footprint",
]

metadata = {
Expand Down
169 changes: 169 additions & 0 deletions src/common/metadata_view.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
#ifndef INFINI_RT_COMMON_METADATA_VIEW_H_
#define INFINI_RT_COMMON_METADATA_VIEW_H_

#include <cstddef>
#include <iterator>
#include <type_traits>
#include <utility>

namespace infini::rt::detail {

template <typename T, std::size_t inline_capacity>
class SmallVector;

template <typename T>
class MetadataView;

template <typename T>
struct IsMetadataView : std::false_type {};

template <typename T>
struct IsMetadataView<MetadataView<T>> : std::true_type {};

template <typename T>
struct IsMetadataViewSmallVector : std::false_type {};

template <typename T, std::size_t inline_capacity>
struct IsMetadataViewSmallVector<SmallVector<T, inline_capacity>>
: std::true_type {};

template <typename Range, typename T, typename = void>
struct IsMetadataViewComparableRange : std::false_type {};

template <typename Range, typename T>
struct IsMetadataViewComparableRange<
Range, T,
std::void_t<decltype(std::begin(std::declval<const Range&>())),
decltype(std::end(std::declval<const Range&>())),
decltype(std::size(std::declval<const Range&>())),
decltype(static_cast<bool>(
std::declval<const T&>() ==
*std::begin(std::declval<const Range&>())))>>
: std::true_type {};

template <typename T>
class MetadataView {
public:
using value_type = T;

using size_type = std::size_t;

using reference = const T&;

using const_reference = const T&;

using pointer = const T*;

using const_pointer = const T*;

using iterator = const T*;

using const_iterator = const T*;

constexpr MetadataView() noexcept = default;

constexpr MetadataView(const_pointer data, size_type size) noexcept
: data_{data}, size_{size} {}

constexpr size_type size() const noexcept { return size_; }

constexpr bool empty() const noexcept { return size_ == 0; }

constexpr const_pointer data() const noexcept { return data_; }

constexpr const_reference front() const noexcept { return data_[0]; }

constexpr const_reference back() const noexcept { return data_[size_ - 1]; }

constexpr const_reference operator[](size_type index) const noexcept {
return data_[index];
}

constexpr const_iterator begin() const noexcept { return data_; }

constexpr const_iterator end() const noexcept {
return empty() ? data_ : data_ + size_;
}

constexpr const_iterator cbegin() const noexcept { return begin(); }

constexpr const_iterator cend() const noexcept { return end(); }

private:
const_pointer data_{nullptr};

size_type size_{0};
};

template <typename Left, typename Right,
std::enable_if_t<
IsMetadataViewComparableRange<MetadataView<Right>, Left>::value,
int> = 0>
constexpr bool operator==(MetadataView<Left> left, MetadataView<Right> right) {
if (left.size() != right.size()) return false;

for (std::size_t index = 0; index < left.size(); ++index) {
if (!(left[index] == right[index])) return false;
}

return true;
}

template <typename Left, typename Right,
std::enable_if_t<
IsMetadataViewComparableRange<MetadataView<Right>, Left>::value,
int> = 0>
constexpr bool operator!=(MetadataView<Left> left, MetadataView<Right> right) {
return !(left == right);
}

template <typename T, typename Range,
std::enable_if_t<
!IsMetadataView<std::decay_t<Range>>::value &&
!IsMetadataViewSmallVector<std::decay_t<Range>>::value &&
IsMetadataViewComparableRange<Range, T>::value,
int> = 0>
constexpr bool operator==(MetadataView<T> left, const Range& right) {
if (left.size() != static_cast<std::size_t>(std::size(right))) return false;

auto right_iterator = std::begin(right);
for (std::size_t index = 0; index < left.size(); ++index, ++right_iterator) {
if (!(left[index] == *right_iterator)) return false;
}

return true;
}

template <typename Range, typename T,
std::enable_if_t<
!IsMetadataView<std::decay_t<Range>>::value &&
!IsMetadataViewSmallVector<std::decay_t<Range>>::value &&
IsMetadataViewComparableRange<Range, T>::value,
int> = 0>
constexpr bool operator==(const Range& left, MetadataView<T> right) {
return right == left;
}

template <typename T, typename Range,
std::enable_if_t<
!IsMetadataView<std::decay_t<Range>>::value &&
!IsMetadataViewSmallVector<std::decay_t<Range>>::value &&
IsMetadataViewComparableRange<Range, T>::value,
int> = 0>
constexpr bool operator!=(MetadataView<T> left, const Range& right) {
return !(left == right);
}

template <typename Range, typename T,
std::enable_if_t<
!IsMetadataView<std::decay_t<Range>>::value &&
!IsMetadataViewSmallVector<std::decay_t<Range>>::value &&
IsMetadataViewComparableRange<Range, T>::value,
int> = 0>
constexpr bool operator!=(const Range& left, MetadataView<T> right) {
return !(right == left);
}

} // namespace infini::rt::detail

#endif
Loading
Loading