Skip to main content

TensorCore.h File

Tensor core types and storage/mapping utilities. More...

Included Headers

#include "pipeline/TensorTypes.h" #include <cstddef> #include <cstdint> #include <functional> #include <memory> #include <optional> #include <string> #include <stdexcept> #include <utility> #include <vector>

Namespaces Index

namespacesimaai
namespaceneat

Classes Index

structDevice
structImageSpec
structAudioSpec
structTokensSpec
structEncodedSpec
structQuantSpec
structTessSpec
structSemantic
structMapping
structSegment
structStorage
structPlane
structNv12View
structNv12Mapped
structI420View
structI420Mapped
structTensor

Description

Tensor core types and storage/mapping utilities.

File Listing

The file content with the documentation metadata removed is:

1
6#pragma once
7
9
10#include <cstddef>
11#include <cstdint>
12#include <functional>
13#include <memory>
14#include <optional>
15#include <string>
16#include <stdexcept>
17#include <utility>
18#include <vector>
19
20#if defined(SIMA_WITH_OPENCV)
21#include <opencv2/core.hpp>
22#endif
23
24namespace simaai::neat {
25
26enum class DeviceType {
27 CPU = 0,
32};
33
34struct Device {
36 int id = 0;
37};
38
39enum class StorageKind {
40 CpuOwned = 0,
45};
46
47enum class PlaneRole {
48 Unknown = 0,
49 Y,
50 U,
51 V,
52 UV,
53};
54
55enum class MapMode {
56 Read = 0,
57 Write,
59};
60
61struct ImageSpec {
62 enum class PixelFormat {
63 RGB = 0,
64 BGR,
65 GRAY8,
66 NV12,
67 I420,
69 };
70
72 std::string color_space;
73};
74
75struct AudioSpec {
76 int sample_rate = 0;
77 int channels = 0;
78 bool interleaved = true;
79};
80
81struct TokensSpec {
82 int vocab_size = 0;
83};
84
85struct EncodedSpec {
86 enum class Codec {
87 H264 = 0,
88 H265,
91 JPEG,
93 };
94
96};
97
98struct QuantSpec {
99 float scale = 1.0f;
100 int32_t zero_point = 0;
101 int axis = -1;
102 std::vector<float> scales;
103 std::vector<int32_t> zero_points;
104};
105
106struct TessSpec {
107 int tile_width = 0;
108 int tile_height = 0;
110 std::string format;
111};
112
113struct Semantic {
114 std::optional<ImageSpec> image;
115 std::optional<AudioSpec> audio;
116 std::optional<TokensSpec> tokens;
117 std::optional<TessSpec> tess;
118 std::optional<EncodedSpec> encoded;
119 std::optional<QuantSpec> quant;
120};
121
122struct Mapping {
123 void* data = nullptr;
124 std::size_t size_bytes = 0;
125 std::function<void()> unmap;
126 std::shared_ptr<void> keepalive;
127
128 Mapping() = default;
129 Mapping(const Mapping&) = delete;
130 Mapping& operator=(const Mapping&) = delete;
131 Mapping(Mapping&& other) noexcept {
132 *this = std::move(other);
133 }
134 Mapping& operator=(Mapping&& other) noexcept {
135 if (this != &other) {
136 if (unmap)
137 unmap();
138 data = other.data;
139 size_bytes = other.size_bytes;
140 unmap = std::move(other.unmap);
141 keepalive = std::move(other.keepalive);
142 other.data = nullptr;
143 other.size_bytes = 0;
144 other.unmap = nullptr;
145 other.keepalive.reset();
146 }
147 return *this;
148 }
150 if (unmap)
151 unmap();
152 }
153};
154
155#if defined(SIMA_WITH_OPENCV)
156struct CvMatView {
157 Mapping mapping;
158 cv::Mat mat;
159};
160#endif
161
162struct Segment {
163 std::string name;
164 std::size_t size_bytes = 0;
165};
166
167struct Storage {
170 std::size_t size_bytes = 0;
171 std::shared_ptr<void> holder;
172 void* data = nullptr;
173 std::function<Mapping(MapMode)> map_fn;
174 std::uint64_t sima_mem_target_flags = 0;
175 std::uint64_t sima_mem_flags = 0;
176 std::vector<Segment> sima_segments;
177
178 Mapping map(MapMode mode) const {
179 Mapping mapping;
180 if (map_fn) {
181 mapping = map_fn(mode);
182 } else {
183 mapping.data = data;
184 mapping.size_bytes = size_bytes;
185 }
186 if (!mapping.keepalive) {
187 mapping.keepalive = holder;
188 }
189 return mapping;
190 }
191};
192
193std::shared_ptr<Storage> make_cpu_owned_storage(std::size_t size_bytes);
194std::shared_ptr<Storage> make_cpu_external_storage(void* data, std::size_t size_bytes,
195 std::shared_ptr<void> holder = {},
196 bool read_only = true);
197
198struct Plane {
200 std::vector<int64_t> shape;
201 std::vector<int64_t> strides_bytes;
202 int64_t byte_offset = 0;
203};
204
205struct Nv12View {
206 int width = 0;
207 int height = 0;
208 const uint8_t* y = nullptr;
209 int64_t y_stride = 0;
210 const uint8_t* uv = nullptr;
211 int64_t uv_stride = 0;
212};
213
214struct Nv12Mapped {
217};
218
219struct I420View {
220 int width = 0;
221 int height = 0;
222 const uint8_t* y = nullptr;
223 int64_t y_stride = 0;
224 const uint8_t* u = nullptr;
225 int64_t u_stride = 0;
226 const uint8_t* v = nullptr;
227 int64_t v_stride = 0;
228};
229
230struct I420Mapped {
233};
234
235struct Tensor {
236 std::shared_ptr<Storage> storage;
239 std::vector<int64_t> shape;
240 std::vector<int64_t> strides_bytes;
241 int64_t byte_offset = 0;
244 std::vector<Plane> planes;
245 bool read_only = true;
246
247 bool is_dense() const {
248 return planes.empty();
249 }
250 bool is_composite() const {
251 return !planes.empty();
252 }
253
254 bool is_contiguous() const {
255 if (shape.empty())
256 return true;
257 if (strides_bytes.empty())
258 return true;
259 std::size_t elem = dtype_bytes(dtype);
260 if (elem == 0)
261 return false;
262 std::int64_t expected = static_cast<std::int64_t>(elem);
263 for (int i = static_cast<int>(shape.size()) - 1; i >= 0; --i) {
264 if (strides_bytes[static_cast<size_t>(i)] != expected)
265 return false;
266 expected *= shape[static_cast<size_t>(i)];
267 }
268 return true;
269 }
270
271 const Plane* try_plane(PlaneRole role) const noexcept {
272 for (const auto& plane : planes) {
273 if (plane.role == role)
274 return &plane;
275 }
276 return nullptr;
277 }
278
279 bool has_plane(PlaneRole role) const noexcept {
280 return try_plane(role) != nullptr;
281 }
282
283 const Plane& plane(PlaneRole role) const {
284 const Plane* found = try_plane(role);
285 if (!found)
286 throw std::runtime_error("Tensor::plane: plane not found");
287 return *found;
288 }
289
290 Mapping map(MapMode mode) const {
291 if (read_only && mode != MapMode::Read) {
292 throw std::runtime_error("Tensor::map: tensor is read-only");
293 }
294 if (!storage)
295 return {};
296 Mapping base = storage->map(mode);
297 if (!base.data)
298 return base;
299 Mapping out = std::move(base);
300 if (!out.keepalive && storage) {
301 out.keepalive = std::static_pointer_cast<void>(storage);
302 }
303 if (byte_offset != 0) {
304 out.data = static_cast<uint8_t*>(out.data) + byte_offset;
305 if (out.size_bytes > static_cast<std::size_t>(byte_offset)) {
306 out.size_bytes = out.size_bytes - static_cast<std::size_t>(byte_offset);
307 }
308 }
309#if defined(NEAT_VALIDATE_ON_MAP)
310 std::string err;
311 if (!validate(&err)) {
312 throw std::runtime_error("Tensor::map: " + err);
313 }
314#endif
315 return out;
316 }
317
318 Mapping map_read() const {
319 return map(MapMode::Read);
320 }
322 return map(MapMode::Write);
323 }
326 return view(MapMode::Read);
327 }
328
329 template <typename T> T* data_ptr() {
330 if (read_only) {
331 throw std::runtime_error("Tensor::data_ptr: tensor is read-only");
332 }
333 return const_cast<T*>(const_data_ptr<T>());
334 }
335
336 template <typename T> const T* data_ptr() const {
337 return const_data_ptr<T>();
338 }
339
341 Tensor clone() const;
342 Tensor to(Device target) const;
343 Tensor cpu() const;
344 Tensor cvu() const;
345 Tensor mla(bool force = false) const;
347 bool validate(std::string* err) const;
348
349 std::optional<Nv12Mapped> map_nv12_read() const;
350 std::size_t nv12_required_bytes() const;
351 bool copy_nv12_contiguous_to(uint8_t* dst, std::size_t dst_size) const;
352 std::vector<uint8_t> copy_nv12_contiguous() const;
353
354 std::optional<I420Mapped> map_i420_read() const;
355 std::size_t i420_required_bytes() const;
356 bool copy_i420_contiguous_to(uint8_t* dst, std::size_t dst_size) const;
357 std::vector<uint8_t> copy_i420_contiguous() const;
358
359 std::size_t dense_bytes_tight() const;
360 bool copy_dense_bytes_tight_to(uint8_t* dst, std::size_t dst_size) const;
361 std::vector<uint8_t> copy_dense_bytes_tight() const;
362
363 bool copy_payload_bytes_to(uint8_t* dst, std::size_t dst_size) const;
364 std::vector<uint8_t> copy_payload_bytes() const;
365
366 int width() const;
367 int height() const;
368 int channels() const;
369 std::optional<ImageSpec::PixelFormat> image_format() const;
370 bool is_nv12() const;
371 bool is_i420() const;
372
373 std::string debug_string() const;
374
375#if defined(SIMA_WITH_OPENCV)
376 static Tensor from_cv_mat(const cv::Mat& mat,
378 bool read_only = true);
379 std::optional<CvMatView> map_cv_mat_view(ImageSpec::PixelFormat desired) const;
380 cv::Mat to_cv_mat_copy(ImageSpec::PixelFormat desired) const;
381#endif
382
383private:
384 template <typename T> const T* const_data_ptr() const {
386 throw std::runtime_error("Tensor::data_ptr: tensor is not on CPU");
387 }
388 if (!is_dense()) {
389 throw std::runtime_error("Tensor::data_ptr: tensor is composite");
390 }
391 if (!is_contiguous()) {
392 throw std::runtime_error("Tensor::data_ptr: call cpu().contiguous() first");
393 }
394 if (!storage || !storage->data) {
395 throw std::runtime_error("Tensor::data_ptr: tensor storage is not mappable");
396 }
397 return reinterpret_cast<const T*>(static_cast<const uint8_t*>(storage->data) + byte_offset);
398 }
399
400 static std::size_t dtype_bytes(simaai::neat::TensorDType dtype) {
401 switch (dtype) {
404 return 1;
408 return 2;
411 return 4;
413 return 8;
414 }
415 return 0;
416 }
417};
418
419} // namespace simaai::neat

Generated via doxygen2docusaurus 2.0.0 by Doxygen 1.9.1.