CANN ops-transformer 旋转位置编码融合算子 aclnnApplyRotaryPosEmbV2 使用指南
算子库人工智能深度学习Ascend【免费下载链接】ops-transformer本项目是CANN提供的transformer类大模型算子库实现网络在NPU上加速计算。项目地址https://gitcode.com/cann/ops-transformer点击查看免费下载导读aclnnApplyRotaryPosEmbV2 是 CANN ops-transformer 仓库中面向推理场景的旋转位置编码RoPERotary Position Embedding融合算子接口它将 Transformer 网络中的 query 与 key 两路位置编码计算融合为一路并在原内存上执行原地更新从而减少 kernel 启动与内存搬运开销。本文基于 aclnnApplyRotaryPosEmbV2.md 展开结合仓库内的算子定义、tiling 实现与可编译示例源码完整讲解该接口的产品支持情况、三种旋转模式的计算公式、两段式接口的完整参数约束、错误码语义以及可直接编译运行的调用示例。读完本文你将掌握如何在 Ascend 推理与训练系列产品上正确选择并调用该接口完成 RoPE 计算并理解其底层 UB 空间约束的由来。接口定位与适用场景功能定位推理网络中attention 计算前需要分别对 query 和 key 施加旋转位置编码。常规做法是调用两个独立的算子分别完成而本接口将两路算子融合成一路一次 kernel 启动同时处理 query 与 key并将计算结果写回原张量原地更新显著减少中间张量生成与内存读写。接口功能执行旋转位置编码计算query、key 两路融合计算结果原地更新。原始输入 query、key 同时作为输出承载计算结果公式中的q_embed、k_embed。与 aclnnApplyRotaryPosEmb 的差异本接口是 aclnnApplyRotaryPosEmb 的功能扩展版本核心差异为新增 rotaryMode 参数用于控制不同的旋转编码方式使同一算子可以适配不同模型对 RoPE 切分方式的实现差异新增rotaryMode旋转模式参数取值范围half、interleave、quarter原接口仅支持 half 类按半切分旋转V2 版本在同一实现上支持三种切分/交织模式。选择建议如果你的模型只使用标准的 half 式旋转且不需要新模式可继续使用原接口需要 interleave/quarter 模式或在 Ascend 950 上使用更多 layout 时选择本 V2 接口。产品支持情况产品是否支持Ascend 950PR / Ascend 950DT支持Atlas A3 训练系列产品 / Atlas A3 推理系列产品支持Atlas A2 训练系列产品 / Atlas A2 推理系列产品支持Atlas 200I/500 A2 推理产品不支持Atlas 推理系列产品支持Atlas 训练系列产品不支持补充说明依据 op_host/apply_rotary_pos_emb_def.cpp 的 AICore 配置除上述产品外仓库还针对kirinx90、kirin9030处理器系列注册了 AICore 配置其约束与 Atlas 推理系列产品一致不支持 BFLOAT16而ascend910bAtlas A2、ascend910_93Atlas A3与ascend950、mc62使用不同的 tiling/regbase 配置。可结合实际目标硬件选择对应配置。旋转位置编码的计算公式接口通过rotaryMode区分三种旋转编码方式。以下公式中q_embed (query * cos) query_rotate * sink_embed (key * cos) key_rotate * sin只是query_rotate/key_rotate的构造方式不同。三种模式的具体切分规则如下。rotaryMode 为 half按半切分后交叉将最后一维从中间一分为二前一半与后一半取负后交叉拼接$$query_q1 query[..., : query.shape[-1] // 2]$$$$query_q2 query[..., query.shape[-1] // 2 :]$$$$query_rotate torch.cat((-query_q2, query_q1), dim-1)$$$$key_k1 key[..., : key.shape[-1] // 2]$$$$key_k2 key[..., key.shape[-1] // 2 :]$$$$key_rotate torch.cat((-key_k2, key_k1), dim-1)$$$$q_embed (query * cos) query_rotate * sin$$$$k_embed (key * cos) key_rotate * sin$$这是大多数 RoPE 实现如 HF 风格的rotate_half采用的模式。rotaryMode 为 quarter四等分交叉将最后一维均分为四段第 2、4 段取负后按 (段2, 段1, 段4, 段3) 顺序拼接$$query_q1 query[..., : query.shape[-1] // 4]$$$$query_q2 query[..., query.shape[-1] // 4 : query.shape[-1] // 2]$$$$query_q3 query[..., query.shape[-1] // 2 : query.shape[-1] // 4 * 3]$$$$query_q4 query[..., query.shape[-1] // 4 * 3 :]$$$$query_rotate torch.cat((-query_q2, query_q1, -query_q4, query_q3), dim-1)$$$$key_q1 key[..., : key.shape[-1] // 4]$$$$key_q2 key[..., key.shape[-1] // 4 : key.shape[-1] // 2]$$$$key_q3 key[..., key.shape[-1] // 2 : key.shape[-1] // 4 * 3]$$$$key_q4 key[..., key.shape[-1] // 4 * 3 :]$$$$key_rotate torch.cat((-key_q2, key_q1, -key_q4, key_q3), dim-1)$$$$q_embed (query * cos) query_rotate * sin$$$$k_embed (key * cos) key_rotate * sin$$rotaryMode 为 interleave奇偶交织按奇偶位置取元素负的偶数位元素与奇数位元素交错拼接回原 shape$$query_q1 query[..., ::2].view(-1, 1)$$$$query_q2 query[..., 1::2].view(-1, 1)$$$$query_rotate torch.cat((-query_q2, query_q1), dim-1).view(query.shape[0], query.shape[1], query.shape[2], query.shape[3])$$$$key_q1 key[..., ::2].view(-1, 1)$$$$key_q2 key[..., 1::2].view(-1, 1)$$$$key_rotate torch.cat((-key_q2, key_q1), dim-1).view(key.shape[0], key.shape[1], key.shape[2], key.shape[3])$$$$q_embed (query * cos) query_rotate * sin$$$$k_embed (key * cos) key_rotate * sin$$注意以上公式以 PyTorch 语法表达切分与拼接语义帮助理解三种模式的区别kernel 内部通过向量指令实现等价计算并非真的逐段 view。三种模式支持的硬件范围Atlas 推理系列产品 / Atlas A2 / Atlas A3仅支持half模式Ascend 950PR / Ascend 950DT支持half、interleave、quarter全部三种模式。同时half与interleave要求输入最后一维能被 2 整除quarter要求最后一维能被 4 整除。两段式接口与函数原型与 CANN 大多数单算子接口一致本算子采用两段式接口调用模型先调用aclnnApplyRotaryPosEmbV2GetWorkspaceSize完成入参校验并计算所需 workspace 大小再调用aclnnApplyRotaryPosEmbV2执行计算。aclnnStatus aclnnApplyRotaryPosEmbV2GetWorkspaceSize( aclTensor *queryRef, aclTensor *keyRef, const aclTensor *cos, const aclTensor *sin, int64_t layout, char *rotaryMode, uint64_t *workspaceSize, aclOpExecutor **executor)aclnnStatus aclnnApplyRotaryPosEmbV2( void *workspace, uint64_t workspaceSize, aclOpExecutor *executor, aclrtStream stream)从源码看V2 接口是对内部统一实现的薄封装op_host/op_api/aclnn_apply_rotary_pos_emb_v2.cpp 中两段接口分别透传给aclnnInnerApplyRotaryPosEmbGetWorkspaceSize与aclnnInnerApplyRotaryPosEmb算子注册在 apply_rotary_pos_emb_def.cpp 中完成算子名 ApplyRotaryPosEmb输入 query/key/cos/sin输出 query/key属性 layout 默认 1、rotary_mode 默认 half。aclnnApplyRotaryPosEmbV2GetWorkspaceSize 参数详解参数说明参数名输入/输出描述使用说明数据类型数据格式维度shape非连续 TensorqueryRefaclTensor输入输出公式中的 query计算结果原地更新见下方分产品约束BFLOAT16、FLOAT16、FLOATNDlayout4 时为 3 维其他 layout 为 4 维√keyRefaclTensor输入输出公式中的 key计算结果原地更新见下方分产品约束BFLOAT16、FLOAT16、FLOATNDlayout4 时为 3 维其他 layout 为 4 维√cosaclTensor输入公式中的 cos见下方分产品约束BFLOAT16、FLOAT16、FLOATNDlayout4 时为 3 维其他 layout 为 4 维√sinaclTensor输入公式中的 sin见下方分产品约束BFLOAT16、FLOAT16、FLOATNDlayout4 时为 3 维其他 layout 为 4 维√layoutint64_t输入输入 Tensor 布局格式1-BSND、2-SBND、3-BNSD、4-TNDint64---rotaryModechar输入旋转模式half、interleave、quarterchar---workspaceSizeuint64_t输出需在 Device 侧申请的 workspace 大小-----executoraclOpExecutor输出op 执行器包含算子计算流程-----四个输入 Tensor 均允许非连续strides 非紧凑传入算子内部按 ND 格式解析。分产品输入约束queryRef / keyRefAtlas 推理系列产品、Atlas A2、Atlas A3不支持空 Tensorshape 最后一维D必须等于 128 或 64。Ascend 950PR / Ascend 950DT支持空 Tensorshape 最后一维D小于等于 1024。cos / sinAtlas 推理系列产品、Atlas A2、Atlas A3不支持空 TensorB 维度与 queryRef、keyRef 一致第 3 维N必须等于 1最后一维D必须等于 128 或 64。Ascend 950PR / Ascend 950DT支持空 TensorB 维度与 queryRef、keyRef 一致或等于 1支持广播N 维度必须等于 1最后一维D小于等于 1024。layout 参数取值范围1-BSND、2-SBND、3-BNSD、4-TND。Atlas 推理系列产品、Atlas A2、Atlas A3支持 1-BSND4 维与 4-TND3 维。Ascend 950PR / Ascend 950DT支持 1-BSND、2-SBND、3-BNSD 的 4 维 Tensor 与 4-TND 的 3 维 Tensor。rotaryMode 参数取值范围half、interleave、quarterAtlas 推理系列产品、Atlas A2、Atlas A3 仅支持halfAscend 950PR / Ascend 950DT 支持全部三种。注意Atlas 推理系列产品不支持 BFLOAT16 输入。返回值与错误码第一段接口返回aclnnStatus出现以下场景时报错返回值错误码描述ACLNN_ERR_PARAM_NULLPTR161001queryRef、keyRef、cos 或 sin 为空指针ACLNN_ERR_PARAM_INVALID161002queryRef、keyRef、cos、sin 的数据类型/数据格式不在支持范围或 shape 不匹配ACLNN_ERR_PARAM_INVALID161002layout 参数不在支持范围内ACLNN_ERR_PARAM_INVALID161002rotaryMode 参数不在支持范围内完整返回码语义参见 aclnn 返回码。aclnnApplyRotaryPosEmbV2 参数详解第二段接口参数说明参数名输入/输出描述workspace输入Device 侧申请的 workspace 内存地址workspaceSize输入Device 侧申请的 workspace 大小由第一段接口获取executor输入op 执行器包含算子计算流程stream输入指定执行任务的 Stream返回aclnnStatus状态码语义见 aclnn 返回码。约束说明与 UB 空间预算确定性计算aclnnApplyRotaryPosEmbV2 为默认确定性实现即相同输入多次执行结果一致便于调试与精度对齐相关概念可参考 确定性计算。Atlas 推理系列产品 / Atlas A2 / Atlas A3 约束layout 为 1 时queryRef、keyRef、cos、sin 前 2 维B、S必须相等layout 为 4 时第 1 维T必须相等。queryRef、keyRef 最后一维D必须相等cos、sin 最后一维D必须相等。四个输入 Tensor 的 dtype 必须相同。shape 记法layout1 时 queryRef 为(q_b, q_s, q_n, q_d)keyRef 为(q_b, q_s, k_n, q_d)cos/sin 为(q_b, q_s, 1, cos_d)layout4 时 queryRef 为(q_t, q_n, q_d)keyRef 为(q_t, k_n, q_d)cos/sin 为(q_t, 1, cos_d)。其中 b 为 batch_size、s 为 seq_length、t 为 b 与 s 合轴、n 为 head_num、d 为 head_dim。UBUnified Buffer空间预算设lastDim为需要旋转位置编码的维度长度根据 dtype 决定 cast 参数输入为 BFLOAT16 时cast 为 1castSize 为 4DtypeSize 为 2输入为 FLOAT16 或 FLOAT32 时cast 为 0castSize DtypeSizeFLOAT16 为 2FLOAT32 为 4。所需 UB 空间估算公式ub_required (q_n k_n) * lastDim * castSize * 2 // 搬运缓冲ping-pong lastDim * DtypeSize * 4 (q_n k_n) * lastDim * castSize // 计算缓冲 (q_n k_n) * lastDim * castSize * 2 cast * (lastDim * 4 * 2) // BF16 转 FP32 的额外开销当ub_required超过当前 AI 处理器的 UB 空间总大小时不支持使用该融合算子。这与 tiling 实现中 apply_rotary_pos_emb_tiling.cpp 的 UB 分配逻辑一致源码中按qPart1Ub搬运(Q_n K_n) * D * castDtypeSize、cosPart1Ub、q2q1Part1Ub计算、sin1UbSizeBF16 cast 场景等分量累加得到speUb再与平台totalUbSize比较决定是否采用小 shape 单核方案或进入多核切分路径平台 UB 大小通过platform_ascendc接口查询如GetCoreMemSize(UB)。Ascend 950PR / Ascend 950DT 约束任意 layout 下queryRef 与 keyRef 除 N 维度外其他维度必须相同。queryRef、keyRef 最后一维D必须相等cos、sin 最后一维D必须相等且小于等于 queryRef、keyRef 的最后一维D。四个输入 Tensor 的 dtype 必须相同。rotaryMode 为 half/interleave 时最后一维必须能被 2 整除quarter 时最后一维必须能被 4 整除。调用示例完整可编译以下示例完整展示从 acl 初始化、构造 aclTensor、两段式调用到结果回拷与资源释放的完整流程代码可直接参照 examples/test_aclnn_apply_rotary_pos_emb_v2.cpp仓库中另有 test_aclnn_apply_rotary_pos_emb.cpp 展示原接口调用方式。编译与运行步骤参考 编译与运行样例。#include acl/acl.h #include aclnnop/aclnn_apply_rotary_pos_emb_v2.h #include iostream #include vector #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 shape_size 1; for (auto i : shape) { shape_size * i; } return shape_size; } 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 0, LOG_PRINT(Init acl failed. ERROR: %d\n, ret); return ret); // 2. 构造输入与输出需要根据API的接口定义构造 // 注意Atlas 推理/A2/A3 上 D 必须为 128 或 64Ascend 950 上 D 1024 std::vectorint64_t queryShape {1, 1, 1, 128}; // BSND std::vectorint64_t keyShape {1, 1, 1, 128}; std::vectorint64_t cosShape {1, 1, 1, 128}; // N 维必须为 1 std::vectorint64_t sinShape {1, 1, 1, 128}; int64_t layout 1; // 1-BSND char rotaryMode[] half; // half / interleave / quarter void* queryDeviceAddr nullptr; void* keyDeviceAddr nullptr; void* cosDeviceAddr nullptr; void* sinDeviceAddr nullptr; aclTensor* query nullptr; aclTensor* key nullptr; aclTensor* cos nullptr; aclTensor* sin nullptr; // host 侧测试数据长度 128 的 FLOAT 序列此处省略中间值完整数据见仓库示例文件 std::vectorfloat queryHostData(128, 1.0f); std::vectorfloat keyHostData(128, 1.0f); std::vectorfloat cosHostData(128, 1.0f); std::vectorfloat sinHostData(128, 1.0f); // 创建 query / key / cos / sin 四个 aclTensor ret CreateAclTensor(queryHostData, queryShape, queryDeviceAddr, aclDataType::ACL_FLOAT, query); CHECK_RET(ret ACL_SUCCESS, return ret); ret CreateAclTensor(keyHostData, keyShape, keyDeviceAddr, aclDataType::ACL_FLOAT, key); CHECK_RET(ret ACL_SUCCESS, return ret); ret CreateAclTensor(cosHostData, cosShape, cosDeviceAddr, aclDataType::ACL_FLOAT, cos); CHECK_RET(ret ACL_SUCCESS, return ret); ret CreateAclTensor(sinHostData, sinShape, sinDeviceAddr, aclDataType::ACL_FLOAT, sin); CHECK_RET(ret ACL_SUCCESS, return ret); // 3. 调用CANN算子库API两段式 uint64_t workspaceSize 0; aclOpExecutor* executor; // 第一段接口入参校验 计算workspace大小 ret aclnnApplyRotaryPosEmbV2GetWorkspaceSize(query, key, cos, sin, layout, rotaryMode, workspaceSize, executor); CHECK_RET(ret ACL_SUCCESS, LOG_PRINT(aclnnApplyRotaryPosEmbV2GetWorkspaceSize 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;); } // 第二段接口执行计算 ret aclnnApplyRotaryPosEmbV2(workspaceAddr, workspaceSize, executor, stream); CHECK_RET(ret ACL_SUCCESS, LOG_PRINT(aclnnApplyRotaryPosEmbV2 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. 获取输出原地更新结果在 query/key 的 device 内存上回拷到 host 侧 auto size GetShapeSize(queryShape); std::vectorfloat resultData(size, 0); ret aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), queryDeviceAddr, size * sizeof(float), ACL_MEMCPY_DEVICE_TO_HOST); CHECK_RET(ret ACL_SUCCESS, LOG_PRINT(copy result from device to host failed. ERROR: %d\n, ret); return ret); for (int64_t i 0; i size; i) { LOG_PRINT(query result[%ld] is: %f\n, i, resultData[i]); } auto size1 GetShapeSize(keyShape); std::vectorfloat resultData1(size1, 0); ret aclrtMemcpy(resultData1.data(), resultData1.size() * sizeof(resultData1[0]), keyDeviceAddr, size1 * sizeof(float), ACL_MEMCPY_DEVICE_TO_HOST); CHECK_RET(ret ACL_SUCCESS, LOG_PRINT(copy result from device to host failed. ERROR: %d\n, ret); return ret); for (int64_t i 0; i size1; i) { LOG_PRINT(key result[%ld] is: %f\n, i, resultData1[i]); } // 6. 释放aclTensor aclDestroyTensor(query); aclDestroyTensor(key); aclDestroyTensor(cos); aclDestroyTensor(sin); // 7. 释放device资源 aclrtFree(queryDeviceAddr); aclrtFree(keyDeviceAddr); aclrtFree(cosDeviceAddr); aclrtFree(sinDeviceAddr); if (workspaceSize 0) { aclrtFree(workspaceAddr); } aclrtDestroyStream(stream); aclrtResetDevice(deviceId); aclFinalize(); return 0; }示例要点示例采用 BSND 布局、FLOAT 类型、half模式shape 为{1, 1, 1, 128}满足 Atlas 推理/A2/A3 与 Ascend 950 两侧的约束结果是原地更新的因此查询结果时直接回拷 queryDeviceAddr / keyDeviceAddr 即可无需额外申请输出张量若要在 Ascend 950 上使用quarter/interleave模式只需修改rotaryMode并确保 D 能被 2/4 整除测试数据、随机初始化细节与完整 128 元素数据序列可在仓库示例文件中查看。仓库中的配套实现与验证资源接口实现op_host/op_api/aclnn_apply_rotary_pos_emb_v2.cpp 与 op_host/op_api/aclnn_apply_rotary_pos_emb_v2.h算子定义op_host/apply_rotary_pos_emb_def.cpp属性 layout 默认 1、rotary_mode 默认 half各产品 AICore 配置shape 推导op_host/apply_rotary_pos_emb_infershape.cpp含 cos/sin 与 query/key 之间的广播维度推导逻辑tiling 实现op_host/apply_rotary_pos_emb_tiling.cpp 及 arch35 系列分路径实现apply_rotary_pos_emb_tiling_ab_arch35.cpp、apply_rotary_pos_emb_tiling_aba_and_ba_arch35.cpp、apply_rotary_pos_emb_tiling_bab_arch35.cppkernel 实现op_kernel/apply_rotary_pos_emb.cpp、op_kernel/apply_rotary_pos_emb_base.h 及 arch35 下的分模式 kernel图融合 passop_graph/fusion_pass/apply_rotary_pos_emb_tensormove_pass.cpp体现该算子在图优化层面与其他算子的融合路径测试与数据生成tests/ut/op_kernel/apply_rotary_pos_emb_data/gen_data.py、tests/ut/op_host/test_apply_rotary_pos_emb_infershape.cpp、tests/ut/op_host/test_apply_rotary_pos_emb_tiling.cpp、tests/ut/op_host/op_api/test_aclnn_apply_rotary_pos_emb.cpp。总结aclnnApplyRotaryPosEmbV2 将 query/key 两路旋转位置编码融合为单次 kernel 执行并原地更新通过新增的 rotaryMode 参数覆盖 half、interleave、quarter 三种主流 RoPE 实现方式。调用前务必核对目标产品的支持矩阵、shape 与 dtype 约束尤其 D 的取值、N 维为 1、四个输入 dtype 一致并遵循两段式接口先计算 workspace 再执行计算的流程。在 Atlas 推理/A2/A3 上仅支持 half 模式且 D 限定为 64/128Ascend 950 上支持全部三种模式、四种 layout 与空 Tensor 场景使用时还需关注ub_required是否超出硬件 UB 空间。结合仓库提供的示例与测试用例可以快速完成该算子在 NPU 上的集成与验证。赞分享算子库人工智能深度学习Ascend【免费下载链接】ops-transformer本项目是CANN提供的transformer类大模型算子库实现网络在NPU上加速计算。项目地址https://gitcode.com/cann/ops-transformer点击查看免费下载相关推荐CANN ops-transformer 中 ApplyRotaryPosEmb 算子旋转位置编码的融合实现与调用指南CANN ops transformer 中 ApplyRotaryPosEmb 算子旋转位置编码的融合实现与调用指南 导读 ApplyRotaryPosEm算子库人工智能深度学习AscendCANN ops-transformer 双路旋转位置编码反向算子 aclnnApplyRotaryPosEmbGrad 使用指南CANN ops transformer 双路旋转位置编码反向算子 aclnnApplyRotaryPosEmbGrad 使用指南 aclnnApplyRota算子库人工智能深度学习AscendCANN ops-transformer apply_rotary_pos_embNPU 上融合双路旋转位置编码的 PyTorch 算子全解析CANN ops transformer apply_rotary_pos_embNPU 上融合双路旋转位置编码的 PyTorch 算子全解析 本指南以 to算子库人工智能深度学习Ascend创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

Linux下安装DB2 v10.5版本

Linux下安装DB2 v10.5版本

1、下载DB2安装包。 百度网盘下载地址: https://download.csdn.net/download/Auspicious_air/92652816 2、把DB2v10.5的安装介质上传到/home目录下并进行解压把DB2v10.5的安装介质上传到/home目录下并进行解压 tar -zxvf v10.5_linuxx64_expc.tar.gz 3、查看解压…

2026/9/21 2:15:12 阅读更多 →
STEP转GLB全流程指南:从CAD精确模型到Web三维展示

STEP转GLB全流程指南:从CAD精确模型到Web三维展示

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/21 2:15:12 阅读更多 →
中文Prompt库选型指南:实测十几站点的筛选标准与实操流程

中文Prompt库选型指南:实测十几站点的筛选标准与实操流程

1. 为什么我要花两周时间把中文 Prompt 库翻个底朝天过去半年,我几乎每天都要跟各种 AI 工具打交道。写代码用 Cursor,画图用 Midjourney 和 Stable Diffusion,做方案用大语言模型,连给团队写周报都习惯先让模型搭个框架。用得越多…

2026/9/21 2:15:11 阅读更多 →

最新新闻

重庆电子地图开发避坑指南:3个源码级细节搞定坐标转换

重庆电子地图开发避坑指南:3个源码级细节搞定坐标转换

重庆电子地图开发避坑指南:3个源码级细节搞定坐标转换 官方文档翻了三遍,核心逻辑还是像一团浆糊。做重庆电子地图项目,卡在坐标偏移问题上整整两天,直到我直接扒了高德和百度的底层源码,才发现坑全藏在转换公式的精度处理里。这份避坑指南不讲虚的,直…

2026/9/22 4:48:06 阅读更多 →
d3dx9_35.dll下载避坑指南:实战项目报错速解

d3dx9_35.dll下载避坑指南:实战项目报错速解

d3dx9_35.dll下载避坑指南:实战项目报错速解 官方文档翻了几百页还是没找到重点?别急,直接看这篇。 做 实战项目 时, d3dx9_35.dll 缺失报错是最让人头大的问题之一。很多初学者一看到 Error: The…

2026/9/22 4:48:06 阅读更多 →
3个坑让思途CMS跑不通? 2026最新选型避坑指南

3个坑让思途CMS跑不通? 2026最新选型避坑指南

3个坑让思途CMS跑不通? 2026最新选型避坑指南 刚把网上抄来的思途CMS代码扔进项目,控制台直接报红, Module not found 和 Undefined variable…

2026/9/22 4:48:06 阅读更多 →
2026最新susi实战项目:告别语法空转,3步搭起全栈应用

2026最新susi实战项目:告别语法空转,3步搭起全栈应用

2026最新susi实战项目:告别语法空转,3步搭起全栈应用 是不是刚啃完Python或JS教程,看着满屏代码点头,真要独立起个项目就发懵?这是无数开发新人的通病:学会语法却不知怎么搭项目。别慌,2026最新的技术栈早已把门槛打平,我们直接…

2026/9/22 4:48:06 阅读更多 →
搞定六顶思维帽:一份前端实现的保姆级教程

搞定六顶思维帽:一份前端实现的保姆级教程

搞定六顶思维帽:一份前端实现的保姆级教程 复制来的代码跑不通,报错信息满屏飞,这是无数开发者深夜加班时的真实写照。你照着教程敲了三天,逻辑看似完美,一运行就崩,根本不知道从哪调起。今天这篇保姆级教程,不讲虚的,直接带你拆解【六顶思维帽】在代…

2026/9/22 4:48:06 阅读更多 →
3个细节搞定老版连连看算法,面试高频考点不再慌

3个细节搞定老版连连看算法,面试高频考点不再慌

3个细节搞定老版连连看算法,面试高频考点不再慌 上周刚帮一个后端同事复盘面试,他在二面挂了。面试官只问了一句:“如果让你实现老版连连看里的路径查找逻辑,怎么保证性能?”他愣了足足十秒,脑子里全是死循环的 BFS…

2026/9/22 4:47:06 阅读更多 →

日新闻

3台商务办公笔记本实测:手写实现环境配置,告别卡半天

3台商务办公笔记本实测:手写实现环境配置,告别卡半天

3台商务办公笔记本实测:手写实现环境配置,告别卡半天 配置环境就卡半天?别怪机器慢,多半是你没选对工具链。在Java、Go或Python的项目现场, 手写实现…

2026/9/22 0:00:41 阅读更多 →
剑帝加点速查手册:3分钟搞懂核心逻辑

剑帝加点速查手册:3分钟搞懂核心逻辑

剑帝加点速查手册:3分钟搞懂核心逻辑 面试被问原理答不上来,是不是常态?别慌。很多开发者对着 GitHub 开源仓库里的代码发呆,看似简单实则暗藏玄机。今天这份【剑帝加点】速查手册,直接带你拆解核心实现,把面试必考的原理讲透。…

2026/9/22 0:00:41 阅读更多 →
手写实现图片压缩网站核心:搞定WebP转换与质量调优

手写实现图片压缩网站核心:搞定WebP转换与质量调优

手写实现图片压缩网站核心:搞定WebP转换与质量调优 复制来的代码跑不通不知道怎么调?别慌,这种“复制粘贴地狱”在开发圈太常见了。尤其是做 图片压缩网站…

2026/9/22 0:00:41 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/22 4:32:41 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/22 4:38:57 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/21 4:51:05 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/21 15:36:51 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/21 15:36:51 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/22 2:43:42 阅读更多 →