数据格式转换处理。将ACL_FORMAT_ND格式转换为ACL_FORMAT_FRACTAL_NZ格式,或将ACL_FORMAT_FRACTAL_NZ格式转换为ACL_FORMAT_ND格式。
ACL_FORMAT_ND = 2:表示支持任意格式,仅Square、Tanh等单输入算子适用。
Format为数据的物理排布格式,定义了解读数据的维度,ND格式表示1D、2D、3D、4D等。以4D为例,N:Batch数量、H:Height,特征图高度、W: Width, 特征图宽度、C: Channel,特征图通道。
以2D为例,一般按照行优先的方式存储。
ACL_FORMAT_FRACTAL_NZ = 29:内部格式,用户目前无需使用。
FRACTAL_NZ是分形格式(NW1H1H0W0),将整个矩阵分为(H1*W1)个分形,每一个分形内部有(H0*W0)个元素对于每一个N层。
以上图为例,N=1、W1=4、H1=4。
硬件型号 |
支持情况 |
特殊说明 |
---|---|---|
|
支持 |
仅支持float16数据类型。 |
|
支持 |
- |
|
支持 |
- |
|
支持 |
- |
1 2 3 4 5 6 7 8 9 10 |
struct TransdataParam { enum TransdataType : int { UNDEFINED = 0, FRACTAL_NZ_TO_ND, ND_TO_FRACTAL_NZ }; TransdataType transdataType = UNDEFINED; SVector<int64_t> outCrops = {0, 0}; uint8_t rsv[8] = {0}; }; |
成员名称 |
类型 |
默认值 |
描述 |
---|---|---|---|
transdataType |
TransdataType |
UNDEFINED |
数据格式转换类型,支持FRACTAL_NZ和ND互相转换。
此默认类型不可用,用户需配置此项参数。 |
outCrops |
SVector<int64_t> |
{0,0} |
仅当FRACTAL_NZ转ND时使用,表示原ND数据格式Shape的最后两维。 |
rsv[8] |
uint8_t |
{0} |
预留参数。 |
参数 |
维度 |
数据类型 |
格式 |
描述 |
---|---|---|---|---|
x |
|
float16/int8/bf16 |
ND |
输入tensor。 |
y |
[batch, n1, m1m0, n0] |
float16/int8/bf16 |
NZ |
输出tensor,数据类型与输入tensor一致。
|
参数 |
维度 |
数据类型 |
格式 |
描述 |
---|---|---|---|---|
x |
[batch, n1, m1m0, n0] |
float16/bf16 |
NZ |
输入tensor。 |
y |
[batch, m, n] |
float16/bf16 |
ND |
输出tensor,数据类型与输入tensor一致。 |
将一个shape为[b, n1, m1m0, n0]的Tensor作为输入,参数中的outCrops = {m, n}。输出tensor的shape为[b, m, n],其中m的取值范围为(,
],n的取值范围为(
,
]。
m0/n0表示对齐位,float16时,n0与m0都为16, int8时,n0为32,m0为16,m1m0表示原始ND的m维度经过对齐位向上对齐,n1表示原始ND的n维度经过对齐位向上对齐后,除以n0的商。例如原始ND的dims为{8, 100, 30},则其对应的NZ的dims为{8, 2, 112, 16}。
前置条件和编译命令请参见算子调用示例。
场景:基础场景。
1 2 3 4 5 6 7 8 9 10 11 12 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 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 93 94 95 96 97 98 99 |
#include <iostream> #include <vector> #include <numeric> #include <random> #include "acl/acl.h" #include "atb/operation.h" #include "atb/types.h" #include "atb/atb_infer.h" #include "demo_util.h" const uint32_t BATCH_SIZE = 8; // 批处理大小 const uint32_t SEQ_LEN = 100; // 序列长度 const uint32_t HIDDEN_SIZE = 30; // 隐藏层维度 /** * @brief 准备atb::VariantPack中的所有输入tensor * @param contextPtr context指针 * @param stream stream * @return atb::SVector<atb::Tensor> 返回一个{[BATCH_SIZE, SEQ_LEN, HIDDEN_SIZE]}的输入Tensors */ atb::SVector<atb::Tensor> PrepareInTensors(atb::Context *contextPtr, aclrtStream stream) { // 创建一个[BATCH_SIZE*SEQ_LEN*HIDDEN_SIZE]的vector,其中各个值为取值范围为[-100,100)的随机数 std::vector<float> inTensorData(BATCH_SIZE * SEQ_LEN * HIDDEN_SIZE, 1.0); // 创建输入Tensor atb::Tensor inTensor = CreateTensorFromVector( contextPtr, stream, inTensorData, ACL_FLOAT16, aclFormat::ACL_FORMAT_ND, {BATCH_SIZE, SEQ_LEN, HIDDEN_SIZE}); atb::SVector<atb::Tensor> inTensors = {inTensor}; return inTensors; } /** * @brief 创建一个 ND转NZ的TransdataOperation,并设置参数 * @return atb::Operation * 返回一个Operation指针 */ atb::Operation *PrepareOperation() { atb::infer::TransdataParam opParam; opParam.transdataType = atb::infer::TransdataParam::TransdataType::ND_TO_FRACTAL_NZ; atb::Operation *transdataOp = nullptr; CHECK_STATUS(atb::CreateOperation(opParam, &transdataOp)); return transdataOp; } int main(int argc, char **argv) { // 设置卡号、创建context、设置stream CHECK_STATUS(aclInit(nullptr)); int32_t deviceId = 0; CHECK_STATUS(aclrtSetDevice(deviceId)); atb::Context *context = nullptr; CHECK_STATUS(atb::CreateContext(&context)); void *stream = nullptr; CHECK_STATUS(aclrtCreateStream(&stream)); context->SetExecuteStream(stream); // TransdataOp ND to NZ示例 atb::Operation *transdataOp = PrepareOperation(); // 准备VariantPack uint32_t ALIGN_16 = 16; atb::VariantPack variantPack; variantPack.inTensors = PrepareInTensors(context, stream); // 放入输入tensor atb::Tensor outTensor = CreateTensor(ACL_FLOAT16, aclFormat::ACL_FORMAT_FRACTAL_NZ, {BATCH_SIZE, (HIDDEN_SIZE + ALIGN_16 - 1) / ALIGN_16, (SEQ_LEN + ALIGN_16 - 1) / ALIGN_16 * ALIGN_16, ALIGN_16}); variantPack.outTensors.push_back(outTensor); // 放入输出tensor uint64_t workspaceSize = 0; // Transdata ND to NZ准备工作 CHECK_STATUS(transdataOp->Setup(variantPack, workspaceSize, context)); uint8_t *workspacePtr = nullptr; if (workspaceSize > 0) { CHECK_STATUS(aclrtMalloc((void **)(&workspacePtr), workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST)); } // Transdata ND to NZ执行 transdataOp->Execute(variantPack, workspacePtr, workspaceSize, context); CHECK_STATUS(aclrtSynchronizeStream(stream)); // 流同步,等待device侧任务计算完成 for (atb::Tensor &inTensor : variantPack.inTensors) { CHECK_STATUS(aclrtFree(inTensor.deviceData)); } for (atb::Tensor &outTensor : variantPack.outTensors) { CHECK_STATUS(aclrtFree(outTensor.deviceData)); } if (workspaceSize > 0) { CHECK_STATUS(aclrtFree(workspacePtr)); } CHECK_STATUS(atb::DestroyOperation(transdataOp)); // operation,对象概念,先释放 std::cout << "Transdata ND to NZ demo success!" << std::endl; // 资源释放 CHECK_STATUS(aclrtDestroyStream(stream)); CHECK_STATUS(atb::DestroyContext(context)); // context,全局资源,后释放 CHECK_STATUS(aclFinalize()); return 0; } |