4.5. Tensor

Tensor是模型推理的输入输出类型,包含了数据信息,实现内存管理。

4.5.1. 构造函数

初始化Tensor,并为Tensor分配内存,如果需要进行系统内存和设备内存的同步,需要执行sync_d2s或sync_s2d

接口形式:
Tensor(
    const std::vector<int>& shape={},
    bm_data_type_t          dtype=BM_FLOAT32);

Tensor(
    Handle                  handle,
    const std::vector<int>& shape,
    bm_data_type_t          dtype=BM_FLOAT32,
    bool                    own_sys_data,
    bool                    own_dev_data);

参数说明:

  • handle: Handle

设备标识Handle

  • shape: std::vector<int>

设置Tensor的shape

  • dtype: Dtype

Tensor的数据类型

  • own_sys_data: bool

指示Tensor是否拥有system memory

  • own_dev_data: bool

指示Tensor是否拥有device memory

示例代码:
#include "tensor.h"

int main() {
    int dev_id = 0;
    int ret;
    sail::Handle handle(dev_id);
    std::shared_ptr<sail::Tensor> input_tensor1,input_tensor2;
    std::vector<int> input_shape = {10,10};
    bm_data_type_t input_dtype = BM_FLOAT32; // dtype can choose  BM_FLOAT32, BM_INT8, BM_UINT8, BM_INT32, BM_UINT32

    // init tensor
    input_tensor1 = std::make_shared<sail::Tensor>(input_shape, input_dtype);
    input_tensor2 = std::make_shared<sail::Tensor>(handle, input_shape, input_dtype, true, true);

    return 0;
}

接口形式3

该初始化方式在一个已存在的源Tensor的基础上创建新Tensor,并复用源Tensor的一部分设备内存,不发生设备内存的数据拷贝。适合LLM推理等复用内存的场景。

在使用该Tensor的过程中,需要保证源Tensor不被释放。

Tensor(const Tensor& src, const std::vector<int>& shape, unsigned int offset);

参数说明3:

  • src: sail::Tensor

创建Tensor所使用的源Tensor

  • shape: std::vector<int>

创建Tensor的shape。需要保证新shape对应的元素个数不超过src的元素个数

  • offset: unsigned int

Tensor的设备内存相对于src的设备内存的偏移量。单位为dtype的字节数

示例代码:
#include <sail/tensor.h>
#include <vector>

int main() {
    sail::Handle handle(0);
    int height = 1080;
    int width = 1920;
    std::vector<int> src_shape = {1, 3, height, width};
    sail::Tensor src_tensor(handle, src_shape, BM_INT32, false, true);

    std::vector<int> dst_shape = {1, 1, height, width};
    unsigned int offset = height * width;
    sail::Tensor dst_tensor(src_tensor, dst_shape, offset);

    return 0;
}

4.5.2. shape

获取Tensor的shape

接口形式:
const std::vector<int>& shape() const;

返回值说明:

  • tensor_shape : std::vector<int>

返回Tensor的shape的vector。

示例代码:
int main() {
    int dev_id = 0;
    int ret;
    sail::Handle handle(dev_id);
    std::shared_ptr<sail::Tensor> input_tensor1;
    std::vector<int> input_shape = {10,10};
    bm_data_type_t input_dtype = BM_FLOAT32;

    // init tensor
    input_tensor1 = std::make_shared<sail::Tensor>(input_shape, input_dtype);

    // get shape
    std::vector<int> tensor_shape;
    tensor_shape = input_tensor1->shape();
    std::cout << "tensor shape: ";
    for(int i = 0; i < tensor_shape.size(); i++) {
        std::cout << tensor_shape[i] << " ";
    }
    std::cout << std::endl;
    return 0;
}

4.5.3. dtype

获取Tensor的数据类型

接口形式:
bm_data_type_t dtype() const;

返回值说明:

  • data_type : bm_data_type_t

返回Tensor的数据类型。

示例代码:
int main() {
    int dev_id = 0;
    int ret;
    sail::Handle handle(dev_id);
    std::shared_ptr<sail::Tensor> input_tensor1;
    std::vector<int> input_shape = {10,10};
    bm_data_type_t input_dtype = BM_FLOAT32;

    // init tensor
    input_tensor1 = std::make_shared<sail::Tensor>(input_shape, input_dtype);

    // get dtype
    bm_data_type_t input_dtype_;
    input_dtype_ = input_tensor1->dtype();
    return 0;
}

4.5.4. scale_from

先对data按比例缩放,再将数据更新到Tensor的系统内存。

接口形式:
void scale_from(float* src, float scale, int size);

参数说明:

  • src: float*

数据的起始地址

  • scale: float32

等比例缩放时的尺度。

  • size: int

数据的长度

示例代码:
int main() {
    int dev_id = 0;
    int ret;
    sail::Handle handle(dev_id);
    std::shared_ptr<sail::Tensor> input_tensor1,input_tensor2;
    std::vector<int> input_shape = {10,10};
    bm_data_type_t input_dtype = BM_FLOAT32;

    // init tensor
    input_tensor1 = std::make_shared<sail::Tensor>(input_shape, input_dtype);

    // prepare data
    std::shared_ptr<float> src_ptr(
            new float[10 * 10],
            std::default_delete<float[]>());
    float * src_data = src_ptr.get();
    for(int i = 0; i < 10 * 10; i++) {
        src_data[i] = rand() % 255;
    }

    // scale data len is 99
    input_tensor1->scale_from(src_data, 0.1, 99);

    return 0;
}

4.5.5. scale_to

先对Tensor进行等比例缩放,再将数据返回到系统内存。

接口形式:
void scale_to(float* dst, float scale);

void scale_to(float* dst, float scale, int size);

参数说明:

  • dst: float*

数据的起始地址。

  • scale: float32

等比例缩放时的尺度。

  • size: int

数据的长度。

示例代码:
int main() {
    int dev_id = 0;
    int ret;
    sail::Handle handle(dev_id);
    std::shared_ptr<sail::Tensor> input_tensor1;
    std::vector<int> input_shape = {10,10};
    bm_data_type_t input_dtype = BM_FLOAT32;

    // init tensor
    input_tensor1 = std::make_shared<sail::Tensor>(input_shape, input_dtype);

    // prepare dst
    float* dst = new float[100];

    // scale data len is 99
    input_tensor1->scale_to(dst, 0.1, 99);

    // print scaled data
    for (int i = 0; i < size; ++i) {
        std::cout << dst[i] << " ";
    }
    std::cout << std::endl;
    delete[] dst;

    return 0;
}

4.5.6. reshape

对Tensor进行reshape

接口形式:
void reshape(const std::vector<int>& shape);

参数说明:

  • shape: std::vector<int>

设置期望得到的新shape。

示例代码:
int main() {
    int dev_id = 0;
    int ret;
    sail::Handle handle(dev_id);
    std::shared_ptr<sail::Tensor> input_tensor1;
    std::vector<int> input_shape = {10,10};
    bm_data_type_t input_dtype = BM_FLOAT32;

    // init tensor
    input_tensor1 = std::make_shared<sail::Tensor>(input_shape, input_dtype);

    // reshape from 10x10 to 2x50
    input_tensor1->reshape({2,50});

    // get shape
    std::vector<int> tensor_shape;
    tensor_shape = input_tensor1->shape();
    std::cout << "tensor new shape: ";
    for(int i = 0; i < tensor_shape.size(); i++) {
        std::cout << tensor_shape[i] << " ";
    }
    std::cout << std::endl;
    return 0;
}

4.5.7. own_sys_data

查询该Tensor是否拥有系统内存的数据指针。

接口形式:
bool& own_sys_data();

返回值说明:

  • judge_ret: bool

如果拥有系统内存的数据指针则返回True,否则False。

示例代码:
int main() {
    int dev_id = 0;
    int ret;
    sail::Handle handle(dev_id);
    std::shared_ptr<sail::Tensor> input_tensor;
    std::vector<int> input_shape = {10,10};
    bm_data_type_t input_dtype = BM_FLOAT32;

    // init tensor
    input_tensor = std::make_shared<sail::Tensor>(handle, input_shape, input_dtype, true, true); // own sys mem:true, own dev mem:true
    // input_tensor = std::make_shared<sail::Tensor>(handle, input_shape, input_dtype, false, true); // own sys mem:true, own dev mem:false

    // input_tensor: own sys or dev data
    bool _own_sys_data = input_tensor->own_sys_data();
    std::cout << "input_tensor own_sys_data:" << _own_sys_data << std::endl;
    return 0;
}

4.5.8. own_dev_data

查询该Tensor是否拥有设备内存的数据

接口形式:
bool& own_dev_data();

返回值说明:

  • judge_ret : bool

如果拥有设备内存中的数据则返回True,否则False。

示例代码:
int main() {
    int dev_id = 0;
    int ret;
    sail::Handle handle(dev_id);
    std::shared_ptr<sail::Tensor> input_tensor;
    std::vector<int> input_shape = {10,10};
    bm_data_type_t input_dtype = BM_FLOAT32;

    // init tensor
    input_tensor = std::make_shared<sail::Tensor>(handle, input_shape, input_dtype, true, true); // own sys mem:true, own dev mem:true
    // input_tensor = std::make_shared<sail::Tensor>(handle, input_shape, input_dtype, true, false); // own sys mem:true, own dev mem:false

    // input_tensor: own sys or dev data
    bool _own_dev_data = input_tensor->own_dev_data();
    std::cout << "input_tensor own_dev_data:" << _own_dev_data << std::endl;

    return 0;
}

4.5.9. sync_s2d

将Tensor中的数据从系统内存拷贝到设备内存。

接口形式:
void sync_s2d();

void sync_s2d(int size);

参数说明:

  • size: int

将特定size字节的数据从系统内存拷贝到设备内存。

接口形式:
void sync_s2d(Tensor* src, int offset_src, int offset_dst, int len);

参数说明:

  • Tensor*: src

指定被拷贝的Tensor。

  • offset_src: int

指定被拷贝Tensor上的数据偏移几个元素后开始拷贝。

  • offset_dst: int

指定拷贝目标Tensor上的数据偏移几个元素后开始拷贝。

  • len: int

指定拷贝长度,既拷贝的元素个数。

示例代码:
int main() {
    int dev_id = 0;
    int ret;
    sail::Handle handle(dev_id);
    std::shared_ptr<sail::Tensor> input_tensor;
    std::vector<int> input_shape = {10,10};
    bm_data_type_t input_dtype = BM_FLOAT32;

    // init tensor
    input_tensor = std::make_shared<sail::Tensor>(handle, input_shape, input_dtype, true, true); // own sys mem:true, own dev mem:true
    // prepare data
    input_tensor->ones();

    // input_tensor -> sync_s2d(); // copy all data
    input_tensor -> sync_s2d(99); // copy part data

    // prepare another data: output_tensor, which is on sys mem, and don't have data
    // copy input_tensor to output_tensor
    std::shared_ptr<sail::Tensor> output_tensor;
    output_tensor = std::make_shared<sail::Tensor>(handle, input_shape, input_dtype, true, true);

    sail::Tensor& input_ref = *input_tensor;
    output_tensor -> sync_s2d(input_ref,2,3,10);

    // test if copy success
    // must copy to system memory and save to dst
    output_tensor -> sync_d2s();
    int size = 100;
    float* dst = new float[size];
    output_tensor->scale_to(dst, 1, size);
    for (int i = 0; i < size; ++i) {
        std::cout << dst[i] << " ";
    }
    std::cout << std::endl;
    delete[] dst;
    return 0;
}

4.5.10. sync_d2s

将Tensor中的数据从设备内存拷贝到系统内存。

接口形式:
void sync_d2s();

void sync_d2s(int size);

参数说明:

  • size: int

将特定size字节的数据从设备内存拷贝到系统内存。

接口形式:
void sync_d2s(Tensor* src, int offset_src, int offset_dst, int len);

参数说明:

  • Tensor*: src

指定被拷贝的Tensor。

  • offset_src: int

指定被拷贝Tensor上的数据偏移几个元素后开始拷贝。

  • offset_dst: int

指定拷贝目标Tensor上的数据偏移几个元素后开始拷贝。

  • len: int

指定拷贝长度,既拷贝的元素个数。

示例代码:
int main() {
    int dev_id = 0;
    int ret;
    sail::Handle handle(dev_id);
    std::shared_ptr<sail::Tensor> input_tensor;
    std::vector<int> input_shape = {10,10};
    bm_data_type_t input_dtype = BM_FLOAT32;

    // init tensor
    input_tensor = std::make_shared<sail::Tensor>(handle, input_shape, input_dtype, false, true); // own sys mem:false, own dev mem:true

    // prepare data
    input_tensor->ones();

    input_tensor -> sync_d2s(); // copy all data
    // input_tensor -> sync_d2s(99); // copy part data

    // prepare another data: output_tensor, which is on sys mem, and don't have data
    // copy input_tensor to output_tensor
    std::shared_ptr<sail::Tensor> output_tensor;
    output_tensor = std::make_shared<sail::Tensor>(handle, input_shape, input_dtype, true, true);

    sail::Tensor& input_ref = *input_tensor;
    output_tensor -> sync_d2s(input_ref,2,3,10);

    // test if copy success
    int size = 100;
    float* dst = new float[size];
    output_tensor->scale_to(dst, 1, size);
    for (int i = 0; i < size; ++i) {
        std::cout << dst[i] << " ";
    }
    std::cout << std::endl;
    delete[] dst;
    return 0;
}

4.5.11. sync_d2d

将另外一个Tensor设备内存上的数据拷贝到本Tensor的设备内存中。

接口形式:
void sync_d2d(Tensor* src, int offset_src, int offset_dst, int len);

参数说明:

  • Tensor*: src

指定被拷贝的Tensor。

  • offset_src: int

指定被拷贝Tensor上的数据偏移几个元素后开始拷贝。

  • offset_dst: int

指定拷贝目标Tensor上的数据偏移几个元素后开始拷贝。

  • len: int

指定拷贝长度,既拷贝的元素个数。

示例代码:
int main() {
    int dev_id = 0;
    int ret;
    sail::Handle handle(dev_id);
    sail::Handle handle_(dev_id+1);
    std::shared_ptr<sail::Tensor> input_tensor,output_tensor;
    std::vector<int> input_shape = {10,10};
    bm_data_type_t input_dtype = BM_FLOAT32;

    // init tensor
    input_tensor = std::make_shared<sail::Tensor>(handle, input_shape, input_dtype, false, true); // on dev0
    output_tensor = std::make_shared<sail::Tensor>(handle_, input_shape, input_dtype, false, true); // on dev1
    // prepare data
    input_tensor -> ones();

    // d2d
    sail::Tensor& input_ref = *input_tensor;
    output_tensor -> sync_d2d(input_ref,1,1,10);

    return 0;
}

4.5.12. sync_d2d_stride

将另外一个Tensor设备内存上的数据拷贝到本Tensor的设备内存中。

接口形式:
void sync_d2d_stride(Tensor* src, int stride_src, int stride_dst, int count);

参数说明:

  • Tensor*: src

指定被拷贝的Tensor。

  • stride_src: int

指定被拷贝Tensor上数据的stride。

  • stride_dst: int

指定拷贝目标Tensor上数据的stride。stride_dst必须是1,除了stride_dst为4且stride_src为1且tensor数据类型大小为1字节的情况。

  • count: int

指定拷贝的元素个数。需要保证count * stride_src <= tensor_src_size, count * stride_dst <= tensor_dst_size。

4.5.13. dump_data

将Tensor中的数据写入到指定文件中,如果需要进行系统内存和设备内存的同步,需要执行sync_d2s

接口形式:
void dump_data(std::string file_name, bool bin = false);

参数说明:

  • file_name: string

写入文件的路径

  • bin: bool

是否采用二进制的形式存储Tensor,默认false.

示例代码:
int main() {
    int dev_id = 0;
    int ret;
    sail::Handle handle(dev_id);
    std::shared_ptr<sail::Tensor> input_tensor;
    std::vector<int> input_shape = {10,10};
    bm_data_type_t input_dtype = BM_FLOAT32;
    // init tensor
    input_tensor = std::make_shared<sail::Tensor>(handle, input_shape, input_dtype, true, true); // own sys mem:true, own dev mem:true
    // prepare data
    input_tensor->ones();

    input_tensor->dump_data("dumped_tensor.txt",false);
    input_tensor->dump_data("dumped_tensor_bin.bin",true);

    return 0;
}

4.5.14. memory_set

用value的前N个字节填充Tensor的内存,N可以是1、2、4,取决于Tensor的dtype。

接口形式:
void memory_set(void* value);

参数说明:

  • value: void*

需要填充的值。

示例代码:
void test_if_success(int size, std::shared_ptr<sail::Tensor> output_tensor){
    float* dst = new float[size];
    output_tensor->scale_to(dst, 1);
    for (int i = 0; i < 100; ++i) {
        std::cout << dst[i] << " ";
    }
    std::cout << std::endl;
    delete[] dst;
}

int main() {
    int dev_id = 0;
    int ret;
    sail::Handle handle(dev_id);
    std::shared_ptr<sail::Tensor> input_tensor;
    std::vector<int> input_shape = {3, 1920, 1080};
    bm_data_type_t input_dtype = BM_FLOAT32;
    input_tensor = std::make_shared<sail::Tensor>(handle,input_shape, input_dtype,true,true);

    float src_data = 1.1;
    // memory set to tensor
    input_tensor->memory_set(src_data);
    test_if_success(3 * 1920 * 1080,input_tensor);

    return 0;
}

4.5.15. memory_set

将本Tensor的数据全部置为c,在接口内部根据本Tensor的dtype对c做相应的类型转换,本接口可能会因为数据类型转换而带来精度损失,建议用上面的memory_set接口。

接口形式:
void memory_set(float c);

参数说明:

  • c: float

需要填充的值。

示例代码:
void test_if_success(int size, std::shared_ptr<sail::Tensor> output_tensor){
    float* dst = new float[size];
    output_tensor->scale_to(dst, 1);
    for (int i = 0; i < size; ++i) {
        std::cout << dst[i] << " ";
    }
    std::cout << std::endl;
    delete[] dst;
}

int main() {
    int dev_id = 0;
    int ret;
    sail::Handle handle(dev_id);
    std::shared_ptr<sail::Tensor> input_tensor;
    std::vector<int> input_shape = {1};
    bm_data_type_t input_dtype = BM_FLOAT32;
    input_tensor = std::make_shared<sail::Tensor>(handle,input_shape, input_dtype,true,true);

    float value_ = 1.1;
    input_tensor->memory_set(value_);
    test_if_success(1,input_tensor);

    return 0;
}

4.5.16. zeros

将本Tensor的数据全部置为0。

接口形式:
void zeros();
示例代码:
int main() {
    int dev_id = 0;
    int ret;
    sail::Handle handle(dev_id);
    std::shared_ptr<sail::Tensor> input_tensor;
    std::vector<int> input_shape = {10,10};
    bm_data_type_t input_dtype = BM_FLOAT32;

    // init tensor
    input_tensor = std::make_shared<sail::Tensor>(handle, input_shape, input_dtype, true, true);
    // prepare data
    input_tensor->zeros();

    return 0;
}

4.5.17. ones

将本Tensor的数据全部置为1。

接口形式:
void ones();
示例代码:
int main() {
    int dev_id = 0;
    int ret;
    sail::Handle handle(dev_id);
    std::shared_ptr<sail::Tensor> input_tensor;
    std::vector<int> input_shape = {10,10};
    bm_data_type_t input_dtype = BM_FLOAT32;

    // init tensor
    input_tensor = std::make_shared<sail::Tensor>(handle, input_shape, input_dtype, true, true);
    // prepare data
    input_tensor->ones();

    return 0;
}

4.5.18. size

返回Tensor包含的元素数量。

接口形式:
int size() const;
示例代码:
int main() {
    int dev_id = 0;
    int ret;
    sail::Handle handle(dev_id);
    std::shared_ptr<sail::Tensor> input_tensor;
    std::vector<int> input_shape = {10,10};
    bm_data_type_t input_dtype = BM_FLOAT32;

    // init tensor
    input_tensor = std::make_shared<sail::Tensor>(handle, input_shape, input_dtype, true, true);
    // Output result
    std::cout << input_tensor->size() << " ";

    return 0;
}

4.5.19. element_size

返回Tensor中单个元素占用的字节数。

接口形式:
int element_size() const;
示例代码:
int main() {
    int dev_id = 0;
    int ret;
    sail::Handle handle(dev_id);
    std::shared_ptr<sail::Tensor> input_tensor;
    std::vector<int> input_shape = {10,10};
    bm_data_type_t input_dtype = BM_FLOAT32;

    // init tensor
    input_tensor = std::make_shared<sail::Tensor>(handle, input_shape, input_dtype, true, true);
    // Output result
    std::cout << input_tensor->element_size() << " ";

    return 0;
}

4.5.20. nbytes

返回Tensor中所有元素占用的总字节数。

接口形式:
int nbytes() const;
示例代码:
int main() {
    int dev_id = 0;
    int ret;
    sail::Handle handle(dev_id);
    std::shared_ptr<sail::Tensor> input_tensor;
    std::vector<int> input_shape = {10,10};
    bm_data_type_t input_dtype = BM_FLOAT32;

    // init tensor
    input_tensor = std::make_shared<sail::Tensor>(handle, input_shape, input_dtype, true, true);
    // Output result
    std::cout << input_tensor->nbytes() << " ";

    return 0;
}