Line data Source code
1 : // SPDX-License-Identifier: Apache-2.0
2 : /**
3 : * @file q4_k_tensor.cpp
4 : * @date 23 April 2025
5 : * @brief This is Q6_K_Tensor class for Q4_K quantized tensor.
6 : * @see https://github.com/nnstreamer/nntrainer
7 : * @author Donghyeon Jeong <dhyeon.jeong@samsung.com>
8 : * @bug No known bugs except for NYI items
9 : */
10 :
11 : #include <cpu_backend.h>
12 : #include <q6_k_tensor.h>
13 : #include <tensor.h>
14 :
15 : namespace nntrainer {
16 :
17 0 : Q6_K_Tensor::Q6_K_Tensor(std::string name_, Tformat fm) :
18 0 : TensorBase(name_, fm) {}
19 :
20 6 : Q6_K_Tensor::Q6_K_Tensor(const TensorDim &d, bool alloc_now, Initializer init,
21 6 : std::string name) :
22 6 : TensorBase(d, false, init, name) {
23 8 : NNTR_THROW_IF(d.batch() != 1 || d.channel() != 1 || d.width() % 256 != 0,
24 : std::invalid_argument)
25 : << "Q6_K_Tensor must be 2 dimensional tensor with batch size 1 and "
26 : "width must be divisible by 256";
27 :
28 4 : if (alloc_now)
29 3 : allocate();
30 6 : }
31 :
32 3 : Q6_K_Tensor::Q6_K_Tensor(const TensorDim &d, const void *buf) :
33 3 : Q6_K_Tensor(d, true, Initializer::NONE, "") {
34 3 : if (d.getDataLen() != 0) {
35 3 : if (buf != nullptr)
36 0 : copy_q6k(buf);
37 : }
38 3 : }
39 :
40 4 : void Q6_K_Tensor::allocate() {
41 4 : if (empty() || data)
42 : return;
43 :
44 4 : if (src_tensor) {
45 : /// allocate data based on the source tensor
46 0 : allocateSrcTensor();
47 : /** as this memory is shared, do NOT initialize */
48 : } else {
49 : /// allocate new memory for the tensor data
50 : MemoryData *mem_data;
51 :
52 16344724 : mem_data = new MemoryData((void *)(new uint8_t[size()]{}));
53 4 : data = std::shared_ptr<MemoryData>(mem_data, [](auto *mem_data) {
54 4 : delete[] mem_data->template getAddr<uint8_t>();
55 4 : delete mem_data;
56 : });
57 :
58 4 : offset = 0;
59 4 : initialize();
60 : }
61 : }
62 :
63 12 : void *Q6_K_Tensor::getData() const {
64 12 : if (!data)
65 : return nullptr;
66 :
67 : data->validate();
68 11 : return data->getAddr<uint8_t>() + offset;
69 : }
70 :
71 17 : size_t Q6_K_Tensor::size() const {
72 17 : size_t num_blocks = height() * width() / 256;
73 17 : return Q6_K_SIZE * num_blocks;
74 : }
75 :
76 0 : size_t Q6_K_Tensor::getMemoryBytes() const { return size() * sizeof(uint8_t); }
77 :
78 0 : void Q6_K_Tensor::copy_q6k(const void *buf) {
79 0 : NNTR_THROW_IF(!contiguous, std::invalid_argument)
80 : << getName() << " is not contiguous, cannot copy.";
81 :
82 0 : if (buf == getData()) {
83 : return;
84 : }
85 : // copy tensor data
86 0 : scopy(size(), (uint8_t *)buf, 1, (uint8_t *)getData(), 1);
87 : }
88 :
89 4 : void Q6_K_Tensor::setZero() {
90 4 : uint8_t *data = (uint8_t *)getData();
91 4 : std::fill(data, data + size(), 0);
92 4 : }
93 :
94 4 : void Q6_K_Tensor::initialize() {
95 4 : if (empty() || !isAllocated())
96 : return;
97 :
98 4 : setZero();
99 4 : putData();
100 : }
101 :
102 1 : QScheme Q6_K_Tensor::q_scheme() const { return QScheme::Q6_K; }
103 :
104 : } // namespace nntrainer
|