tensor.cpp 10 KB
Newer Older
PanZezhong's avatar
init  
PanZezhong committed
1
2
#include "../tensor.hpp"
#include "../utils.hpp"
3
#include <algorithm>
PanZezhong's avatar
init  
PanZezhong committed
4
5
6
#include <fstream>
#include <iostream>
#include <numeric>
PanZezhong's avatar
PanZezhong committed
7
#include <sstream>
PanZezhong's avatar
init  
PanZezhong committed
8
9
10
11

std::shared_ptr<TensorDesc>
TensorDesc::create(infiniDtype_t dtype, const std::vector<size_t> &shape,
                   const std::vector<ptrdiff_t> &strides) {
PanZezhong's avatar
PanZezhong committed
12
    return std::shared_ptr<TensorDesc>(new TensorDesc(dtype, shape, strides));
PanZezhong's avatar
init  
PanZezhong committed
13
14
}

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
std::shared_ptr<TensorDesc>
TensorDesc::create(infiniDtype_t dtype, const std::vector<size_t> &shape) {
    auto ndim = shape.size();
    auto strides = std::vector<ptrdiff_t>(ndim);
    if (ndim > 0) {
        strides[ndim - 1] = 1;
        for (int i = ndim - 2; i >= 0; i--) {
            strides[i] = strides[i + 1] * shape[i + 1];
        }
    }
    return create(dtype, shape, strides);
}

std::shared_ptr<TensorDesc>
TensorDesc::createWithOrder(infiniDtype_t dtype, const std::vector<size_t> &shape,
                            const std::vector<size_t> &order) {
    ASSERT_EQ(shape.size(), order.size());
    auto ndim = shape.size();
    if (ndim == 0) {
        return create(dtype, shape);
    }
    auto strides = std::vector<ptrdiff_t>(order.size());
    auto idx = std::find(order.begin(), order.end(), size_t(ndim - 1));
    strides[std::distance(order.begin(), idx)] = 1;
    for (int i = ndim - 2; i >= 0; i--) {
        auto prev_dim = shape[std::distance(order.begin(), idx)];
        auto prev_stride = strides[std::distance(order.begin(), idx)];
        idx = std::find(order.begin(), order.end(), size_t(i));
        strides[std::distance(order.begin(), idx)] = prev_stride * prev_dim;
    }
    return create(dtype, shape, strides);
}

PanZezhong's avatar
PanZezhong committed
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
infiniopTensorDescriptor_t TensorDesc::desc() const {
    if (_desc == nullptr) {
        RUN_INFINI(infiniopCreateTensorDescriptor(
            (infiniopTensorDescriptor_t *)(&_desc), _shape.size(), _shape.data(),
            _strides.data(), _dtype));
    }
    return _desc;
};

void TensorDesc::resetDesc() {
    if (this->_desc != nullptr) {
        infiniopDestroyTensorDescriptor(this->_desc);
        this->_desc = nullptr;
    }
}

bool TensorDesc::isContigous() const {
    auto ndim = this->ndim();
    auto shape = this->shape();
    auto strides = std::vector<ptrdiff_t>(ndim);
    strides[ndim - 1] = 1;
    for (int i = ndim - 2; i >= 0; i--) {
        strides[i] = strides[i + 1] * shape[i + 1];
    }
    ASSERT_EQ(strides.size(), this->_strides.size());
    return std::equal(strides.begin(), strides.end(), this->_strides.begin());
}

std::string TensorDesc::info() const {
    std::stringstream ss;

    ss << "Tensor: "
       << "shape[ ";
    for (auto s : this->shape()) {
        ss << s << " ";
    }
    ss << "] strides[ ";
    for (auto s : this->strides()) {
        ss << s << " ";
    }
    ss << "] dtype=" << this->dtype();

    return ss.str();
}

PanZezhong's avatar
init  
PanZezhong committed
93
TensorDesc::~TensorDesc() {
PanZezhong's avatar
PanZezhong committed
94
    this->resetDesc();
PanZezhong's avatar
init  
PanZezhong committed
95
96
}

PanZezhong's avatar
PanZezhong committed
97
98
99
100
101
102
const std::vector<size_t> &Tensor::shape() const { return this->_desc->shape(); }
const std::vector<ptrdiff_t> &Tensor::strides() const { return this->_desc->strides(); }
size_t Tensor::ndim() const { return this->_desc->ndim(); }
infiniDtype_t Tensor::dtype() const { return this->_desc->dtype(); }
infiniDevice_t Tensor::deviceType() const { return this->_storage->deviceType(); }
int Tensor::deviceId() const { return this->_storage->deviceId(); }
PanZezhong's avatar
init  
PanZezhong committed
103
104
Tensor::~Tensor() {}

PanZezhong's avatar
PanZezhong committed
105
ptrdiff_t Tensor::dataOffset() const {
PanZezhong's avatar
PanZezhong committed
106
    return _offset;
PanZezhong's avatar
init  
PanZezhong committed
107
108
}

PanZezhong's avatar
PanZezhong committed
109
infiniopTensorDescriptor_t Tensor::desc() const { return _desc->desc(); }
PanZezhong's avatar
init  
PanZezhong committed
110
111
112

std::shared_ptr<Tensor> Tensor::buffer(infiniDtype_t dtype,
                                       const std::vector<size_t> &shape,
thatPepe's avatar
thatPepe committed
113
                                       std::shared_ptr<MemoryPool> pool) {
PanZezhong's avatar
init  
PanZezhong committed
114
115
    std::shared_ptr<Tensor> tensor = std::make_shared<Tensor>();
    auto ndim = shape.size();
PanZezhong's avatar
PanZezhong committed
116

PanZezhong's avatar
init  
PanZezhong committed
117
118
    size_t size = std::accumulate(shape.begin(), shape.end(), dsize(dtype), std::multiplies<size_t>());
    auto strides = std::vector<ptrdiff_t>(ndim);
PanZezhong's avatar
PanZezhong committed
119
120
121
122
123
    if (ndim > 0) {
        strides[ndim - 1] = 1;
        for (int i = ndim - 2; i >= 0; i--) {
            strides[i] = strides[i + 1] * shape[i + 1];
        }
PanZezhong's avatar
init  
PanZezhong committed
124
    }
thatPepe's avatar
thatPepe committed
125
    tensor->_storage = Storage::createFromPool(size, pool);
PanZezhong's avatar
PanZezhong committed
126
    tensor->_desc = TensorDesc::create(dtype, shape, strides);
PanZezhong's avatar
init  
PanZezhong committed
127
128
129
130
131
132
133
134
135
136
    tensor->_offset = 0;
    return tensor;
}

std::shared_ptr<Tensor> Tensor::weight(void *data, infiniDtype_t dtype,
                                       const std::vector<size_t> &shape) {
    std::shared_ptr<Tensor> tensor = std::make_shared<Tensor>();
    auto ndim = shape.size();
    size_t size = std::accumulate(shape.begin(), shape.end(), dsize(dtype), std::multiplies<size_t>());
    auto strides = std::vector<ptrdiff_t>(ndim);
PanZezhong's avatar
PanZezhong committed
137
138
139
140
141
    if (ndim > 0) {
        strides[ndim - 1] = 1;
        for (int i = ndim - 2; i >= 0; i--) {
            strides[i] = strides[i + 1] * shape[i + 1];
        }
PanZezhong's avatar
init  
PanZezhong committed
142
    }
PanZezhong's avatar
PanZezhong committed
143

PanZezhong's avatar
PanZezhong committed
144
    tensor->_storage = Storage::create(size);
PanZezhong's avatar
PanZezhong committed
145
146
    tensor->_desc = TensorDesc::create(dtype, shape, strides);
    RUN_INFINI(infinirtMemcpy(tensor->_storage->memory(),
PanZezhong's avatar
init  
PanZezhong committed
147
                              data, size, INFINIRT_MEMCPY_H2D));
PanZezhong's avatar
PanZezhong committed
148

PanZezhong's avatar
init  
PanZezhong committed
149
150
151
152
    tensor->_offset = 0;
    return tensor;
}

PanZezhong's avatar
PanZezhong committed
153
154
std::shared_ptr<Tensor> Tensor::memShare(const std::vector<size_t> &shape, infiniDtype_t dtype_) const {
    auto dtype = dtype_ == INFINI_DTYPE_INVALID ? this->dtype() : dtype_;
155
    size_t size = std::accumulate(shape.begin(), shape.end(), dsize(dtype), std::multiplies<size_t>());
PanZezhong's avatar
PanZezhong committed
156
    ASSERT(size <= this->_storage->size());
157
158
159
160
161
162
163
164
165
166
167
168

    std::shared_ptr<Tensor> tensor = std::make_shared<Tensor>();
    auto ndim = shape.size();
    auto strides = std::vector<ptrdiff_t>(ndim);
    if (ndim > 0) {
        strides[ndim - 1] = 1;
        for (int i = ndim - 2; i >= 0; i--) {
            strides[i] = strides[i + 1] * shape[i + 1];
        }
    }
    tensor->_storage = this->_storage;
    tensor->_offset = 0;
PanZezhong's avatar
PanZezhong committed
169
    tensor->_desc = TensorDesc::create(dtype, shape, strides);
170
171
172
    return tensor;
}

PanZezhong's avatar
PanZezhong committed
173
void *Tensor::dataImpl(ptrdiff_t offset) const {
PanZezhong's avatar
PanZezhong committed
174
    return (char *)(this->_storage->memory()) + this->_offset + offset * dsize(this->dtype());
PanZezhong's avatar
init  
PanZezhong committed
175
176
177
}

void *Tensor::data(ptrdiff_t offset) {
PanZezhong's avatar
PanZezhong committed
178
    return this->dataImpl(offset);
PanZezhong's avatar
init  
PanZezhong committed
179
180
181
}

const void *Tensor::data(ptrdiff_t offset) const {
PanZezhong's avatar
PanZezhong committed
182
    return this->dataImpl(offset);
PanZezhong's avatar
init  
PanZezhong committed
183
184
}

PanZezhong's avatar
PanZezhong committed
185
186
void Tensor::copyFrom(std::shared_ptr<Tensor const> src,
                      infiniopHandle_t handle, infinirtStream_t stream) {
PanZezhong's avatar
init  
PanZezhong committed
187
188
189
190
    ASSERT_EQ(this->shape(), src->shape());
    ASSERT_EQ(this->dtype(), src->dtype());
    infiniopRearrangeDescriptor_t desc;
    RUN_INFINI(infiniopCreateRearrangeDescriptor(
PanZezhong's avatar
PanZezhong committed
191
        handle, &desc, this->desc(), src->desc()));
PanZezhong's avatar
init  
PanZezhong committed
192
193
194
195
196
    RUN_INFINI(infiniopRearrange(desc, this->data(), src->data(),
                                 stream));
    RUN_INFINI(infiniopDestroyRearrangeDescriptor(desc));
}

PanZezhong's avatar
PanZezhong committed
197
198
bool Tensor::isContigous() const {
    return this->_desc->isContigous();
PanZezhong's avatar
init  
PanZezhong committed
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
}

template <typename T>
void print_data(T *data, const std::vector<size_t> &shape,
                const std::vector<ptrdiff_t> &strides, size_t dim) {
    if (dim == shape.size() - 1) {
        for (size_t i = 0; i < shape[dim]; i++) {
            std::cout << data[i] << " ";
        }
        std::cout << std::endl;
    } else if (dim < shape.size() - 1) {
        for (size_t i = 0; i < shape[dim]; i++) {
            print_data(data + i * strides[dim], shape, strides, dim + 1);
        }
    }
}

template <>
void print_data(uint16_t const *data, const std::vector<size_t> &shape,
                const std::vector<ptrdiff_t> &strides, size_t dim) {
    if (dim == shape.size() - 1) {
        for (size_t i = 0; i < shape[dim]; i++) {
            std::cout << f16_to_f32(data[i * strides[dim]]) << " ";
        }
PanZezhong's avatar
PanZezhong committed
223
        std::cout << std::endl;
PanZezhong's avatar
init  
PanZezhong committed
224
225
226
227
228
229
230
    } else if (dim < shape.size() - 1) {
        for (size_t i = 0; i < shape[dim]; i++) {
            print_data(data + i * strides[dim], shape, strides, dim + 1);
        }
    }
}

PanZezhong's avatar
PanZezhong committed
231
232
233
234
std::string Tensor::info() const {
    std::stringstream ss;

    ss << "Tensor: "
PanZezhong's avatar
PanZezhong committed
235
       << this->_desc->info()
PanZezhong's avatar
PanZezhong committed
236
237
       << " device=" << this->deviceType()
       << " device_id=" << this->deviceId();
PanZezhong's avatar
PanZezhong committed
238
    return this->_desc->info();
PanZezhong's avatar
PanZezhong committed
239
240
241
}

void Tensor::debug(const std::string &filename) const {
PanZezhong's avatar
PanZezhong committed
242
243
    RUN_INFINI(infinirtDeviceSynchronize());

PanZezhong's avatar
PanZezhong committed
244
    std::cout << info() << std::endl;
PanZezhong's avatar
PanZezhong committed
245

PanZezhong's avatar
init  
PanZezhong committed
246
    void const *cpu_data;
PanZezhong's avatar
PanZezhong committed
247
    if (this->deviceType() != INFINI_DEVICE_CPU) {
PanZezhong's avatar
PanZezhong committed
248
249
250
        void *cpu_memory = std::malloc(this->_storage->size());
        RUN_INFINI(infinirtMemcpy(cpu_memory, this->_storage->memory(),
                                  this->_storage->size(), INFINIRT_MEMCPY_D2H));
PanZezhong's avatar
init  
PanZezhong committed
251
252
        cpu_data = cpu_memory;
    } else {
PanZezhong's avatar
PanZezhong committed
253
        cpu_data = this->_storage->memory();
PanZezhong's avatar
init  
PanZezhong committed
254
255
256
257
258
259
260
261
    }

    if (!filename.empty()) {
        std::ofstream outFile(filename, std::ios::binary);
        if (!outFile) {
            std::cerr << "Error opening file for writing: " << filename << "\n";
            return;
        }
PanZezhong's avatar
PanZezhong committed
262
        outFile.write(reinterpret_cast<const char *>(cpu_data), this->_storage->size());
PanZezhong's avatar
init  
PanZezhong committed
263
264
265
266
267
        outFile.close();
        std::cout << "Data written to file: " << filename << "\n";
        return;
    }

PanZezhong's avatar
PanZezhong committed
268
    switch (this->dtype()) {
PanZezhong's avatar
init  
PanZezhong committed
269
    case INFINI_DTYPE_F16:
PanZezhong's avatar
PanZezhong committed
270
        print_data((uint16_t const *)((char const *)cpu_data + dataOffset()),
PanZezhong's avatar
init  
PanZezhong committed
271
272
273
                   this->shape(), this->strides(), 0);
        break;
    case INFINI_DTYPE_F32:
PanZezhong's avatar
PanZezhong committed
274
        print_data((float const *)((char const *)cpu_data + dataOffset()),
PanZezhong's avatar
init  
PanZezhong committed
275
276
277
                   this->shape(), this->strides(), 0);
        break;
    case INFINI_DTYPE_U64:
PanZezhong's avatar
PanZezhong committed
278
        print_data((uint64_t const *)((char const *)cpu_data + dataOffset()),
PanZezhong's avatar
init  
PanZezhong committed
279
280
281
                   this->shape(), this->strides(), 0);
        break;
    case INFINI_DTYPE_I64:
PanZezhong's avatar
PanZezhong committed
282
        print_data((int64_t const *)((char const *)cpu_data + dataOffset()),
PanZezhong's avatar
init  
PanZezhong committed
283
284
285
                   this->shape(), this->strides(), 0);
        break;
    case INFINI_DTYPE_U32:
PanZezhong's avatar
PanZezhong committed
286
        print_data((uint32_t const *)((char const *)cpu_data + dataOffset()),
PanZezhong's avatar
init  
PanZezhong committed
287
288
289
                   this->shape(), this->strides(), 0);
        break;
    case INFINI_DTYPE_I32:
PanZezhong's avatar
PanZezhong committed
290
        print_data((int32_t const *)((char const *)cpu_data + dataOffset()),
PanZezhong's avatar
init  
PanZezhong committed
291
292
293
294
295
296
297
298
                   this->shape(), this->strides(), 0);
        break;
    default:
        PANIC("Unsupported data type");
    }
}

void Tensor::debug() const { this->debug(""); }