| 430 | } |
| 431 | |
| 432 | class ImmutableTensor::DevValueCache final : public UserDataContainer::UserData { |
| 433 | MGB_TYPEINFO_OBJ_DECL; |
| 434 | CompNode m_comp_node; |
| 435 | |
| 436 | class TensorKey { |
| 437 | struct Trait { |
| 438 | size_t hash = 0, size_bytes = 0; |
| 439 | TensorLayout layout; |
| 440 | }; |
| 441 | Trait m_trait; |
| 442 | std::vector<dt_byte> m_val; |
| 443 | HostTensorND m_val_ref; |
| 444 | |
| 445 | const dt_byte* val_ptr() const { |
| 446 | mgb_assert(m_trait.size_bytes); |
| 447 | return m_val.empty() ? m_val_ref.raw_ptr() : m_val.data(); |
| 448 | } |
| 449 | |
| 450 | public: |
| 451 | TensorKey() = default; |
| 452 | TensorKey(const HostTensorND& v) : m_val_ref{v} { |
| 453 | mgb_assert(v.layout().is_contiguous() || v.layout().is_empty()); |
| 454 | m_trait.size_bytes = v.layout().span().high_byte; |
| 455 | |
| 456 | auto&& layout = m_trait.layout; |
| 457 | // zero to enable byte-comparison |
| 458 | memset(&layout, 0, sizeof(layout)); |
| 459 | layout.ndim = v.layout().ndim; |
| 460 | layout.dtype = v.layout().dtype; |
| 461 | for (size_t i = 0; i < layout.ndim; ++i) { |
| 462 | layout.shape[i] = v.layout().shape[i]; |
| 463 | layout.stride[i] = v.layout().stride[i]; |
| 464 | } |
| 465 | XXHash hasher; |
| 466 | if (!v.empty()) { |
| 467 | hasher.update(v.raw_ptr(), m_trait.size_bytes); |
| 468 | } |
| 469 | hasher.update(&m_trait.layout, sizeof(m_trait.layout)); |
| 470 | m_trait.hash = hasher.digest(); |
| 471 | } |
| 472 | |
| 473 | bool operator==(const TensorKey& rhs) const { |
| 474 | return !memcmp(&m_trait, &rhs.m_trait, sizeof(Trait)) && |
| 475 | ((m_trait.size_bytes == 0 && rhs.m_trait.size_bytes == 0) || |
| 476 | !memcmp(val_ptr(), rhs.val_ptr(), m_trait.size_bytes)); |
| 477 | } |
| 478 | |
| 479 | size_t hash() const { return m_trait.hash; } |
| 480 | |
| 481 | //! copy from m_val_ref to m_val, to avoid refed value being |
| 482 | //! modified |
| 483 | void copy_val_permanent() { |
| 484 | if (m_trait.size_bytes == 0) |
| 485 | return; |
| 486 | mgb_assert(m_val.empty()); |
| 487 | m_val.resize(m_trait.size_bytes); |
| 488 | memcpy(m_val.data(), m_val_ref.raw_ptr(), m_trait.size_bytes); |
| 489 | m_val_ref = {}; |
nothing calls this directly
no test coverage detected