aclnnConfusionTranspose【免费下载链接】ops-math本项目是CANN提供的数学类基础计算算子库实现网络在NPU上加速计算。项目地址: https://gitcode.com/cann/ops-math产品支持情况产品是否支持Ascend 950PR/Ascend 950DT√Atlas A3 训练系列产品/Atlas A3 推理系列产品xAtlas A2 训练系列产品/Atlas A2 推理系列产品xAtlas 200I/500 A2 推理产品×Atlas 推理系列产品xAtlas 训练系列产品x功能说明接口功能融合reshape和transpose运算。计算公式transposeFirst为False时$$ ytranspose(reshape(x,shape),perm) $$transposeFirst为True时$$ yreshape(transpose(x,perm),shape) $$函数原型每个算子分为两段式接口必须先调用aclnnConfusionTransposeGetWorkspaceSize接口获取入参并根据计算流程计算所需workspace大小再调用aclnnConfusionTranspose接口执行计算。aclnnStatus aclnnConfusionTransposeGetWorkspaceSize( const aclTensor *x, const aclIntArray *perm, const aclIntArray *shape, bool transposeFirst, aclTensor *out, uint64_t *workspaceSize, aclOpExecutor **executor)aclnnStatus aclnnConfusionTranspose( void *workspace, uint64_t workspaceSize, aclOpExecutor *executor, aclrtStream stream)aclnnConfusionTransposeGetWorkspaceSize参数说明参数名输入/输出描述使用说明数据类型数据格式维度(shape)非连续TensorxaclTensor*输入/输出输入Tensor对应公式中的x。支持空tensor。INT8、INT16、 INT32、 INT64、UINT8、UINT16、UINT32、UINT64、FLOAT16、FLOAT、BFLOAT16ND1-8-permaclIntArray*输入转置后每根轴对应的转置前轴索引对应公式中的perm。1、该输入中元素必须唯一并在[0,perm的维度数量-1]范围内。2、当transposeFirst为True时perm的长度必须与x的shape的长度相同即len(perm)len(x_shape)。3、当transposeFirst为False时perm长度必须与属性输入shape的长度相同即len(perm)len(shape)。INT64---shapeaclIntArray*输入reshape后的shape大小对应公式中的shape。shape中的所有维度乘积必须等于输入张量 x 的元素总数。INT64---transposeFirstbool输入判断是否先执行transpose操作。如果值为True 首先执行transpose否则先执行 reshape 。BOOL---outaclTensor*输出表示reshape和transpose之后的计算结果。-与输入x保持一致与输入x保持一致--workspaceSize(uint64_t*)输出返回需要在Device侧申请的workspace大小。-----executor(aclOpExecutor**)输出返回op执行器包含了算子计算流程。-----返回值aclnnStatus返回状态码具体参见aclnn返回码。第一段接口完成入参校验出现以下场景时报错返回值错误码描述ACLNN_ERR_PARAM_NULLPTR161001传入的 x 或 out 是空指针。ACLNN_ERR_PARAM_INVALID161002传入的 x 、out 的数据类型不在支持的范围之内。ACLNN_ERR_INNER_NULLPTR561103API内部校验错误通常由于输入数据或属性的规格不在支持的范围之内/输入和输出的 shape 不满足参数说明中的要求。aclnnConfusionTranspose参数说明参数名输入/输出描述workspace输入在Device侧申请的workspace内存地址。workspaceSize输入在Device侧申请的workspace大小由第一段接口aclnnConfusionTransposeGetWorkspaceSize获取。executor输入op执行器包含了算子计算流程。stream输入指定执行任务的Stream。返回值aclnnStatus返回状态码具体参见aclnn返回码。约束说明确定性说明aclnnConfusionTranspose默认确定性实现。例如设 shape_before 为 reshape 操作前的数据形状shape_after 为 reshape 操作后的数据形状 shape_before [(ab),(cd),f,(gh)] shape_after [a,(bc),d,e,(fg),h] 而如下的 shape_after 是不被允许的 shape_after_illegal [a,b,d,e,(fg),(ch)]调用示例示例代码如下仅供参考具体编译和执行过程请参考编译与运行样例。#include iostream #include vector #include acl/acl.h #include aclnnop/aclnn_confusion_transpose.h #define CHECK_RET(cond, return_expr) \ do { \ if (!(cond)) { \ return_expr; \ } \ } while (0) #define LOG_PRINT(message, ...) \ do { \ printf(message, ##__VA_ARGS__); \ } while (0) int64_t GetShapeSize(const std::vectorint64_t shape) { int64_t shapeSize 1; for (auto i : shape) { shapeSize * i; } return shapeSize; } void PrintOutResult(std::vectorint64_t shape, void** deviceAddr) { auto size GetShapeSize(shape); std::vectorfloat resultData(size, 0); auto ret aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), *deviceAddr, size * sizeof(resultData[0]), ACL_MEMCPY_DEVICE_TO_HOST); CHECK_RET(ret ACL_SUCCESS, LOG_PRINT(copy result from device to host failed. ERROR: %d\n, ret); return); for (int64_t i 0; i size; i) { LOG_PRINT(mean result[%ld] is: %f\n, i, resultData[i]); } } int Init(int32_t deviceId, aclrtStream* stream) { // 固定写法资源初始化 auto ret aclInit(nullptr); CHECK_RET(ret ACL_SUCCESS, LOG_PRINT(aclInit failed. ERROR: %d\n, ret); return ret); ret aclrtSetDevice(deviceId); CHECK_RET(ret ACL_SUCCESS, LOG_PRINT(aclrtSetDevice failed. ERROR: %d\n, ret); return ret); ret aclrtCreateStream(stream); CHECK_RET(ret ACL_SUCCESS, LOG_PRINT(aclrtCreateStream failed. ERROR: %d\n, ret); return ret); return 0; } template typename T int CreateAclTensor(const std::vectorT hostData, const std::vectorint64_t shape, void** deviceAddr, aclDataType dataType, aclTensor** tensor) { auto size GetShapeSize(shape) * sizeof(T); // 调用aclrtMalloc申请device侧内存 auto ret aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); CHECK_RET(ret ACL_SUCCESS, LOG_PRINT(aclrtMalloc failed. ERROR: %d\n, ret); return ret); // 调用aclrtMemcpy将host侧数据复制到device侧内存上 ret aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE); CHECK_RET(ret ACL_SUCCESS, LOG_PRINT(aclrtMemcpy failed. ERROR: %d\n, ret); return ret); // 计算连续tensor的strides std::vectorint64_t strides(shape.size(), 1); for (int64_t i shape.size() - 2; i 0; i--) { strides[i] shape[i 1] * strides[i 1]; } // 调用aclCreateTensor接口创建aclTensor *tensor aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, shape.data(), shape.size(), *deviceAddr); return 0; } int main() { // 1. 固定写法device/stream初始化参考acl API手册 // 根据自己的实际device填写deviceId int32_t deviceId 0; aclrtStream stream; auto ret Init(deviceId, stream); CHECK_RET(ret ACL_SUCCESS, LOG_PRINT(Init acl failed. ERROR: %d\n, ret); return ret); // 2. 构造输入与输出需要根据API的接口自定义构造 // 创建input aclTensor aclTensor* x nullptr; std::vectorint64_t xShape {2, 4}; std::vectorfloat xHostData {1, 2, 3, 4, 5, 6, 7, 8}; void* xDeviceAddr nullptr; ret CreateAclTensor(xHostData, xShape, xDeviceAddr, aclDataType::ACL_FLOAT, x); CHECK_RET(ret ACL_SUCCESS, return ret); // 创建perm aclIntArray* perm nullptr; std::vectorint64_t permData {1, 0}; perm aclCreateIntArray(permData.data(), permData.size()); CHECK_RET(perm ! nullptr, return ret); // 创建shape aclIntArray* shape nullptr; std::vectorint64_t shapeData {2, 4}; shape aclCreateIntArray(shapeData.data(), shapeData.size()); CHECK_RET(shape ! nullptr, return ret); // 创建transposeFirst bool transposeFirst true; // 创建output aclTensor std::vectorint64_t outShape {2, 4}; std::vectorfloat outHostData(8, 1); aclTensor* out nullptr; void* outDeviceAddr nullptr; // 创建out aclTensor ret CreateAclTensor(outHostData, outShape, outDeviceAddr, aclDataType::ACL_FLOAT, out); CHECK_RET(ret ACL_SUCCESS, return ret); // 3. 调用CANN算子库API需要修改为具体的Api名称 uint64_t workspaceSize 16 * 1024 * 1024; aclOpExecutor* executor; // 调用aclnnConfusionTranspose第一段接口 ret aclnnConfusionTransposeGetWorkspaceSize(x, perm, shape, transposeFirst, out, workspaceSize, executor); CHECK_RET(ret ACL_SUCCESS, LOG_PRINT(aclnnConfusionTransposeGetWorkspaceSize failed. ERROR: %d\n, ret); return ret); // 根据第一段接口计算出的workspaceSize申请device内存 void* workspaceAddr nullptr; if (workspaceSize 0) { ret aclrtMalloc(workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); CHECK_RET(ret ACL_SUCCESS, LOG_PRINT(allocate workspace failed. ERROR: %d\n, ret); return ret); } // 调用aclnnConfusionTranspose第二段接口 ret aclnnConfusionTranspose(workspaceAddr, workspaceSize, executor, stream); CHECK_RET(ret ACL_SUCCESS, LOG_PRINT(aclnnConfusionTranspose failed. ERROR: %d\n, ret); return ret); // 4. 固定写法同步等待任务执行结束 ret aclrtSynchronizeStream(stream); CHECK_RET(ret ACL_SUCCESS, LOG_PRINT(aclrtSynchronizeStream failed. ERROR: %d\n, ret); return ret); // 5. 获取输出的值将device侧内存上的结果复制至host侧需要根据具体API的接口定义修改 PrintOutResult(outShape, outDeviceAddr); // 6. 释放aclTensor和aclTensor需要根据具体API的接口定义修改 aclDestroyTensor(x); aclDestroyTensor(out); // 7.释放device资源需要根据具体API的接口定义修改 aclrtFree(xDeviceAddr); aclrtFree(outDeviceAddr); if (workspaceSize 0) { aclrtFree(workspaceAddr); } aclrtDestroyStream(stream); aclrtResetDevice(deviceId); aclFinalize(); return 0; }【免费下载链接】ops-math本项目是CANN提供的数学类基础计算算子库实现网络在NPU上加速计算。项目地址: https://gitcode.com/cann/ops-math创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考