已合并
update inplace_partial_rotary_mul_grad doc #8143
update inplace_partial_rotary_mul_grad doc #8143
已合并
AlfengYuan创建于 7月3日
5 个文件变更+364-13
Mdocs/zh/ascend950_op_list.md+11-1
@@ -886,6 +886,16 @@ Ascend 950支持的算子分类和算子列表如下:
886 <td>AI Core</td>886 <td>AI Core</td>
887 <td>执行旋转位置编码计算,推理网络为了提升性能,将query和key两路算子融合成一路。</td>887 <td>执行旋转位置编码计算,推理网络为了提升性能,将query和key两路算子融合成一路。</td>
888 </tr>888 </tr>
889+ <tr>
890+ <td>posembedding</td>
891+ <td><a href="../../posembedding/inplace_partial_rotary_mul_grad/README.md">inplace_partial_rotary_mul_grad</a></td>
892+ <td>✓</td>
893+ <td>✓</td>
894+ <td>✓</td>
895+ <td>✓</td>
896+ <td>AI Core</td>
897+ <td>执行局部旋转位置编码InplacePartialRotaryMul的反向计算,对输入dy的D维度上切片[start, end)区域执行旋转位置编码梯度计算,结果inplace写回dy。</td>
898+ </tr>
889 <tr>899 <tr>
890 <td>posembedding</td>900 <td>posembedding</td>
891 <td><a href="../../posembedding/kv_rms_norm_rope_cache/README.md">kv_rms_norm_rope_cache</a></td>901 <td><a href="../../posembedding/kv_rms_norm_rope_cache/README.md">kv_rms_norm_rope_cache</a></td>
@@ -957,4 +967,4 @@ Ascend 950支持的算子分类和算子列表如下:
957 <td>示例算子,用于演示算子开发流程。</td>967 <td>示例算子,用于演示算子开发流程。</td>
958 </tr>968 </tr>
959</tbody>969</tbody>
960-</table>970+</table>
Mdocs/zh/op_api_list.md+1-0
@@ -108,6 +108,7 @@
108|[aclnnInplaceAttentionWorkerScheduler](../../attention/attention_worker_scheduler/docs/aclnnInplaceAttentionWorkerScheduler.md)|Attention和FFN分离部署场景下,Attention侧数据扫描算子。该算子接收来自FFNToAttention算子的输出数据,并对数据进行逐步扫描,确保数据准备就绪。|默认确定性实现| 默认确定性实现 |108|[aclnnInplaceAttentionWorkerScheduler](../../attention/attention_worker_scheduler/docs/aclnnInplaceAttentionWorkerScheduler.md)|Attention和FFN分离部署场景下,Attention侧数据扫描算子。该算子接收来自FFNToAttention算子的输出数据,并对数据进行逐步扫描,确保数据准备就绪。|默认确定性实现| 默认确定性实现 |
109|[aclnnInplaceFfnWorkerScheduler](../../ffn/ffn_worker_scheduler/docs/aclnnInplaceFfnWorkerScheduler.md)|Attention和FFN分离场景下,FFN侧数据扫描算子。该算子接收AttentionToFFN算子发送的数据,进行扫描并完成数据整理。|默认确定性实现| 默认确定性实现 |109|[aclnnInplaceFfnWorkerScheduler](../../ffn/ffn_worker_scheduler/docs/aclnnInplaceFfnWorkerScheduler.md)|Attention和FFN分离场景下,FFN侧数据扫描算子。该算子接收AttentionToFFN算子发送的数据,进行扫描并完成数据整理。|默认确定性实现| 默认确定性实现 |
110|[aclnnInplacePartialRotaryMul](../../posembedding/inplace_partial_rotary_mul/docs/aclnnInplacePartialRotaryMul.md)|执行单路旋转位置编码的Inplace计算,直接修改输入张量,不产生新的输出张量。|默认确定性实现| 默认确定性实现 |110|[aclnnInplacePartialRotaryMul](../../posembedding/inplace_partial_rotary_mul/docs/aclnnInplacePartialRotaryMul.md)|执行单路旋转位置编码的Inplace计算,直接修改输入张量,不产生新的输出张量。|默认确定性实现| 默认确定性实现 |
111+|[aclnnInplacePartialRotaryMulGrad](../../posembedding/inplace_partial_rotary_mul_grad/docs/aclnnInplacePartialRotaryMulGrad.md)|执行局部旋转位置编码InplacePartialRotaryMul的反向计算,对输入dy的D维度上切片[start, end)区域执行旋转位置编码梯度计算,结果inplace写回dy。|- | 默认确定性实现 |
111|[aclnnInterleaveRope](../../posembedding/interleave_rope/docs/aclnnInterleaveRope.md)|针对单输入x进行旋转位置编码。|- | 默认确定性实现 |112|[aclnnInterleaveRope](../../posembedding/interleave_rope/docs/aclnnInterleaveRope.md)|针对单输入x进行旋转位置编码。|- | 默认确定性实现 |
112|[aclnnKvCompressEpilog](../../attention/kv_compress_epilog/docs/aclnnKvCompressEpilog.md)|在KV Cache的Epilog阶段,对缓存进行原地逐组动态量化压缩更新,将bfloat16激活值压缩为FP8格式并按slotMapping散写。|- | 默认确定性实现 |113|[aclnnKvCompressEpilog](../../attention/kv_compress_epilog/docs/aclnnKvCompressEpilog.md)|在KV Cache的Epilog阶段,对缓存进行原地逐组动态量化压缩更新,将bfloat16激活值压缩为FP8格式并按slotMapping散写。|- | 默认确定性实现 |
113|[aclnnLightningIndexer](../../attention/lightning_indexer/docs/aclnnLightningIndexer.md)|稀疏attention前处理的计算,目的是选出关键的稀疏token位置。|默认确定性实现| 默认确定性实现 |114|[aclnnLightningIndexer](../../attention/lightning_indexer/docs/aclnnLightningIndexer.md)|稀疏attention前处理的计算,目的是选出关键的稀疏token位置。|默认确定性实现| 默认确定性实现 |
Mdocs/zh/op_list.md+10-0
@@ -1306,6 +1306,16 @@
1306 <td>AI Core</td>1306 <td>AI Core</td>
1307 <td>执行单路旋转位置编码的Inplace计算,直接修改输入张量,不产生新的输出张量。</td>1307 <td>执行单路旋转位置编码的Inplace计算,直接修改输入张量,不产生新的输出张量。</td>
1308 </tr>1308 </tr>
1309+ <tr>
1310+ <td>posembedding</td>
1311+ <td><a href="../../posembedding/inplace_partial_rotary_mul_grad/README.md">inplace_partial_rotary_mul_grad</a></td>
1312+ <td>✓</td>
1313+ <td>✓</td>
1314+ <td>✓</td>
1315+ <td>✓</td>
1316+ <td>AI Core</td>
1317+ <td>执行局部旋转位置编码InplacePartialRotaryMul的反向计算,对输入dy的D维度上切片[start, end)区域执行旋转位置编码梯度计算,结果inplace写回dy。</td>
1318+ </tr>
1309 <tr>1319 <tr>
1310 <td>posembedding</td>1320 <td>posembedding</td>
1311 <td><a href="../../posembedding/qkv_rms_norm_rope_cache/README.md">qkv_rms_norm_rope_cache</a></td>1321 <td><a href="../../posembedding/qkv_rms_norm_rope_cache/README.md">qkv_rms_norm_rope_cache</a></td>
Mposembedding/inplace_partial_rotary_mul_grad/README.md+13-12
@@ -126,9 +126,9 @@
126</thead>126</thead>
127<tbody>127<tbody>
128 <tr>128 <tr>
129- <td>dyRef</td>129+ <td>dy</td>
130 <td>输入</td>130 <td>输入</td>
131- <td>公式中的dy,表示正向计算输出y的导数,inplace更新为正向输入x的导数。Inplace模式,dyRef同时作为输出写入结果。</td>131+ <td>公式中的dy,表示正向计算输出y的导数,inplace更新为正向输入x的导数。Inplace模式,dy同时作为输出写入结果。</td>
132 <td>BFLOAT16、FLOAT16、FLOAT32</td>132 <td>BFLOAT16、FLOAT16、FLOAT32</td>
133 <td>ND</td>133 <td>ND</td>
134 </tr>134 </tr>
@@ -147,14 +147,14 @@
147 <td>ND</td>147 <td>ND</td>
148 </tr>148 </tr>
149 <tr>149 <tr>
150- <td>rotaryMode</td>150+ <td>rotary_mode</td>
151 <td>属性</td>151 <td>属性</td>
152- <td>旋转模式,0=half,1=interleave,2=quarter,3=interleave-half。</td>152+ <td>旋转模式,0=half,1=interleave,2=quarter,3=interleave-half。当前仅支持interleave模式(rotary_mode=1)。</td>
153 <td>INT64</td>153 <td>INT64</td>
154 <td>-</td>154 <td>-</td>
155 </tr>155 </tr>
156 <tr>156 <tr>
157- <td>partialSlice</td>157+ <td>partial_slice</td>
158 <td>属性</td>158 <td>属性</td>
159 <td>D维度上的切片范围[start, end),默认{0, 0}表示不做有效计算。start须在[0, D]内,end须在[start, D]内。</td>159 <td>D维度上的切片范围[start, end),默认{0, 0}表示不做有效计算。start须在[0, D]内,end须在[start, D]内。</td>
160 <td>IntArray</td>160 <td>IntArray</td>
@@ -168,13 +168,13 @@
168- 该算子仅支持Ascend 950 AI Processor。168- 该算子仅支持Ascend 950 AI Processor。
169- 该算子仅支持连续Tensor,不支持非连续Tensor。169- 该算子仅支持连续Tensor,不支持非连续Tensor。
170- 该算子当前版本仅支持 interleave 模式(`rotary_mode=1`)。其他模式暂不支持。170- 该算子当前版本仅支持 interleave 模式(`rotary_mode=1`)。其他模式暂不支持。
171-- Inplace执行:输入dyRef和输出共享同一个Tensor,计算结果直接写回输入dyRef171+- Inplace执行:输入dy和输出共享同一个Tensor,计算结果直接写回输入dy
172-- 输入dyRef当前只支持BSND排布,输入cos/sin的shape必须与dyRef满足B/S/N维度的广播关系(如BSND、111D、1SND、B1ND、BS1D、11ND、B11D、1S1D等)。各参数的shape约束可以描述如下:172+- 输入dy当前只支持BSND排布,输入cos/sin的shape必须与dy满足B/S/N维度的广播关系(如BSND、111D、1SND、B1ND、BS1D、11ND、B11D、1S1D等)。各参数的shape约束可以描述如下:
173- - 输入张量dyRef的最后一维大小D必须小于等于1024。173+ - 输入张量dy的最后一维大小D必须小于等于1024。
174- - 输入张量cos、sin的最后一维大小必须等于切片长度(end - start)174+ - 输入张量cos、sin的最后一维大小必须等于partial_slice的切片长度(即partial_slice[1] - partial_slice[0])
175- - 输入张量cos和sin的shape必须完全相同,cos和sin的B、S、N维度需要与dyRef满足[broadcast关系](../../docs/zh/context/broadcast关系.md),且广播后的B、S、N必须等于dyRef的B、S、N。175+ - 输入张量cos和sin的shape必须完全相同,cos和sin的B、S、N维度需要与dy满足[broadcast关系](../../docs/zh/context/broadcast关系.md),且广播后的B、S、N必须等于dy的B、S、N。
176- - half、interleave和interleave-half模式下,切片长度(end - start)必须能被2整除。176+ - half、interleave和interleave-half模式下,partial_slice切片长度(即partial_slice[1] - partial_slice[0])必须能被2整除。
177- - quarter模式下,切片长度(end - start)必须能被4整除。177+ - quarter模式下,partial_slice切片长度(即partial_slice[1] - partial_slice[0])必须能被4整除。
178 - 当start等于end时,算子不执行有效计算,直接返回。178 - 当start等于end时,算子不执行有效计算,直接返回。
179 - 输入张量cos和sin的数据类型必须相同。179 - 输入张量cos和sin的数据类型必须相同。
180 180 
@@ -184,3 +184,4 @@
184| 调用方式 | 调用样例 | 说明 |184| 调用方式 | 调用样例 | 说明 |
185|----------------|-----------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------|185|----------------|-----------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------|
186| aclnn调用 | [test_aclnn_inplace_partial_rotary_mul_grad](./examples/arch35/test_aclnn_inplace_partial_rotary_mul_grad.cpp) | 通过[aclnnInplacePartialRotaryMulGrad](./docs/aclnnInplacePartialRotaryMulGrad.md)接口方式调用InplacePartialRotaryMulGrad算子。 |186| aclnn调用 | [test_aclnn_inplace_partial_rotary_mul_grad](./examples/arch35/test_aclnn_inplace_partial_rotary_mul_grad.cpp) | 通过[aclnnInplacePartialRotaryMulGrad](./docs/aclnnInplacePartialRotaryMulGrad.md)接口方式调用InplacePartialRotaryMulGrad算子。 |
187+| 图模式调用 | [test_geir_inplace_partial_rotary_mul_grad](./examples/arch35/test_geir_inplace_partial_rotary_mul_grad.cpp) | 通过[算子IR](./op_graph/inplace_partial_rotary_mul_grad_proto.h)构图方式调用InplacePartialRotaryMulGrad算子。 |
Aposembedding/inplace_partial_rotary_mul_grad/examples/arch35/test_geir_inplace_partial_rotary_mul_grad.cpp+329-0
@@ -0,0 +1,329 @@
1+/**
2+ * Copyright (c) 2026 Huawei Technologies Co., Ltd.
3+ * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4+ * CANN Open Software License Agreement Version 2.0 (the "License").
5+ * Please refer to the License for details. You may not use this file except in compliance with the License.
6+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7+ * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8+ * See LICENSE in the root of the software repository for the full text of the License.
9+ */
10+ 
11+#include <cstdint>
12+#include <cstdio>
13+#include <cstdlib>
14+#include <ctime>
15+#include <fstream>
16+#include <iostream>
17+#include <map>
18+#include <string>
19+#include <vector>
20+ 
21+#include "ge_api.h"
22+#include "ge_api_types.h"
23+#include "ge_error_codes.h"
24+#include "ge_ir_build.h"
25+#include "ops_proto_legacy.h"
26+#include "graph.h"
27+#include "tensor.h"
28+#include "types.h"
29+ 
30+#include "../../op_graph/inplace_partial_rotary_mul_grad_proto.h"
31+ 
32+#define FAILED (-1)
33+#define SUCCESS 0
34+ 
35+using namespace ge;
36+using std::map;
37+using std::string;
38+using std::vector;
39+ 
40+namespace {
41+constexpr int64_t kBatch = 1;
42+constexpr int64_t kSeqLen = 1;
43+constexpr int64_t kNumHeads = 1;
44+constexpr int64_t kHeadDim = 128;
45+constexpr int64_t kSliceStart = 0;
46+constexpr int64_t kSliceEnd = 128;
47+constexpr int64_t kRotaryMode = 1;
48+ 
49+string GetTime()
50+{
51+ time_t timep;
52+ time(&timep);
53+ char tmp[64];
54+ strftime(tmp, sizeof(tmp), "%Y-%m-%d %H:%M:%S,000", localtime(&timep));
55+ return tmp;
56+}
57+ 
58+uint32_t GetDataTypeSize(DataType dt)
59+{
60+ if (dt == DT_FLOAT || dt == DT_INT32 || dt == DT_UINT32) {
61+ return 4;
62+ }
63+ if (dt == DT_FLOAT16 || dt == DT_BF16 || dt == DT_INT16 || dt == DT_UINT16) {
64+ return 2;
65+ }
66+ if (dt == DT_INT64 || dt == DT_UINT64) {
67+ return 8;
68+ }
69+ return 1;
70+}
71+ 
72+int64_t GetShapeSize(const vector<int64_t> &shape)
73+{
74+ int64_t size = 1;
75+ for (auto dim : shape) {
76+ size *= dim;
77+ }
78+ return size;
79+}
80+ 
81+template <typename T>
82+int32_t GenTensorData(const vector<int64_t> &shape, Tensor &tensor, TensorDesc &desc, T value)
83+{
84+ desc.SetRealDimCnt(shape.size());
85+ const int64_t elemNum = GetShapeSize(shape);
86+ const uint64_t dataSize = static_cast<uint64_t>(elemNum) * sizeof(T);
87+ T *data = new (std::nothrow) T[elemNum];
88+ if (data == nullptr) {
89+ return FAILED;
90+ }
91+ for (int64_t i = 0; i < elemNum; ++i) {
92+ data[i] = value;
93+ }
94+ tensor = Tensor(desc, reinterpret_cast<uint8_t *>(data), dataSize);
95+ return SUCCESS;
96+}
97+ 
98+int32_t GenInputData(const vector<int64_t> &shape, Tensor &tensor, TensorDesc &desc, DataType dataType, float value)
99+{
100+ if (dataType == DT_FLOAT) {
101+ return GenTensorData<float>(shape, tensor, desc, value);
102+ }
103+ if (dataType == DT_FLOAT16 || dataType == DT_BF16) {
104+ return GenTensorData<uint16_t>(shape, tensor, desc, static_cast<uint16_t>(value));
105+ }
106+ return FAILED;
107+}
108+ 
109+int32_t WriteDataToFile(const string &binFile, uint64_t dataSize, uint8_t *inputData)
110+{
111+ FILE *fp = fopen(binFile.c_str(), "wb");
112+ if (fp == nullptr) {
113+ return FAILED;
114+ }
115+ fwrite(inputData, sizeof(uint8_t), dataSize, fp);
116+ fclose(fp);
117+ return SUCCESS;
118+}
119+ 
120+int32_t CreateInputTensor(const vector<int64_t> &shape, DataType dtype, float value, TensorDesc &desc, Tensor &tensor)
121+{
122+ desc = TensorDesc(ge::Shape(shape), FORMAT_ND, dtype);
123+ desc.SetPlacement(ge::kPlacementHost);
124+ desc.SetFormat(FORMAT_ND);
125+ 
126+ auto ret = GenInputData(shape, tensor, desc, dtype, value);
127+ if (ret != SUCCESS) {
128+ printf("%s - ERROR - [XIR]: Generate input data failed\n", GetTime().c_str());
129+ return FAILED;
130+ }
131+ return SUCCESS;
132+}
133+ 
134+int32_t ParseDeviceId(int argc, char *argv[])
135+{
136+ // Prefer an explicit command-line device id, then fall back to ASCEND_DEVICE_ID.
137+ const char *deviceIdText = nullptr;
138+ if (argc > 1) {
139+ deviceIdText = argv[1];
140+ } else {
141+ deviceIdText = std::getenv("ASCEND_DEVICE_ID");
142+ }
143+ if (deviceIdText == nullptr || deviceIdText[0] == '\0') {
144+ return 0;
145+ }
146+ 
147+ char *endPtr = nullptr;
148+ long deviceId = std::strtol(deviceIdText, &endPtr, 10);
149+ if (endPtr == deviceIdText || *endPtr != '\0' || deviceId < 0) {
150+ return 0;
151+ }
152+ return static_cast<int32_t>(deviceId);
153+}
154+ 
155+int CreateOppInGraph(DataType inDtype, vector<Tensor> &input, vector<Operator> &inputs, vector<Operator> &outputs,
156+ Graph &graph)
157+{
158+ // Build one GEIR custom-op node. Input and output port names match inplace_partial_rotary_mul_grad_proto.h.
159+ auto inplacePartialRotaryMulGradOp = op::InplacePartialRotaryMulGrad("test_geir_inplace_partial_rotary_mul_grad");
160+ 
161+ vector<int64_t> dyShape = {kBatch, kSeqLen, kNumHeads, kHeadDim};
162+ vector<int64_t> cosShape = {kBatch, kSeqLen, kNumHeads, kSliceEnd - kSliceStart};
163+ vector<int64_t> sinShape = {kBatch, kSeqLen, kNumHeads, kSliceEnd - kSliceStart};
164+ 
165+ TensorDesc dyDesc;
166+ TensorDesc cosDesc;
167+ TensorDesc sinDesc;
168+ Tensor dyTensor;
169+ Tensor cosTensor;
170+ Tensor sinTensor;
171+ 
172+ Status ret = CreateInputTensor(dyShape, inDtype, 2.0f, dyDesc, dyTensor);
173+ if (ret != SUCCESS) {
174+ return FAILED;
175+ }
176+ ret = CreateInputTensor(cosShape, inDtype, 1.0f, cosDesc, cosTensor);
177+ if (ret != SUCCESS) {
178+ return FAILED;
179+ }
180+ ret = CreateInputTensor(sinShape, inDtype, 0.0f, sinDesc, sinTensor);
181+ if (ret != SUCCESS) {
182+ return FAILED;
183+ }
184+ 
185+ // Register runtime graph inputs in the same order as the input tensor vector passed to RunGraph.
186+ auto dyData = op::Data("dy").set_attr_index(0);
187+ dyData.update_input_desc_x(dyDesc);
188+ dyData.update_output_desc_y(dyDesc);
189+ input.push_back(dyTensor);
190+ graph.AddOp(dyData);
191+ inputs.push_back(dyData);
192+ 
193+ auto cosData = op::Data("cos").set_attr_index(1);
194+ cosData.update_input_desc_x(cosDesc);
195+ cosData.update_output_desc_y(cosDesc);
196+ input.push_back(cosTensor);
197+ graph.AddOp(cosData);
198+ inputs.push_back(cosData);
199+ 
200+ auto sinData = op::Data("sin").set_attr_index(2);
201+ sinData.update_input_desc_x(sinDesc);
202+ sinData.update_output_desc_y(sinDesc);
203+ input.push_back(sinTensor);
204+ graph.AddOp(sinData);
205+ inputs.push_back(sinData);
206+ 
207+ inplacePartialRotaryMulGradOp.set_input_dy(dyData);
208+ inplacePartialRotaryMulGradOp.set_input_cos(cosData);
209+ inplacePartialRotaryMulGradOp.set_input_sin(sinData);
210+ inplacePartialRotaryMulGradOp.update_input_desc_dy(dyDesc);
211+ inplacePartialRotaryMulGradOp.update_input_desc_cos(cosDesc);
212+ inplacePartialRotaryMulGradOp.update_input_desc_sin(sinDesc);
213+ 
214+ vector<int64_t> partialSlice = {kSliceStart, kSliceEnd};
215+ inplacePartialRotaryMulGradOp.set_attr_rotary_mode(kRotaryMode);
216+ inplacePartialRotaryMulGradOp.set_attr_partial_slice(partialSlice);
217+ 
218+ // InplacePartialRotaryMulGrad writes the result back to dy; GEIR still exposes dy as the graph output.
219+ inplacePartialRotaryMulGradOp.update_output_desc_dy(dyDesc);
220+ outputs.push_back(inplacePartialRotaryMulGradOp);
221+ return SUCCESS;
222+}
223+} // namespace
224+ 
225+int main(int argc, char *argv[])
226+{
227+ // bash build.sh --run_example inplace_partial_rotary_mul_grad graph
228+ const char *graphName = "tc_ge_irrun_test";
229+ Graph graph(graphName);
230+ vector<Tensor> input;
231+ int32_t deviceId = ParseDeviceId(argc, argv);
232+ string deviceIdStr = std::to_string(deviceId);
233+ 
234+ printf("%s - INFO - [XIR]: Start to initialize ge on device %d using ge global options\n", GetTime().c_str(),
235+ deviceId);
236+ map<AscendString, AscendString> globalOptions = {{"ge.exec.deviceId", deviceIdStr.c_str()},
237+ {"ge.graphRunMode", "1"}};
238+ Status ret = GEInitialize(globalOptions);
239+ if (ret != SUCCESS) {
240+ printf("%s - ERROR - [XIR]: Initialize ge using ge global options failed. ERROR: %d\n", GetTime().c_str(), ret);
241+ return FAILED;
242+ }
243+ printf("%s - INFO - [XIR]: Initialize ge using ge global options success\n", GetTime().c_str());
244+ 
245+ vector<Operator> inputs;
246+ vector<Operator> outputs;
247+ DataType inDtype = DT_FLOAT;
248+ 
249+ ret = CreateOppInGraph(inDtype, input, inputs, outputs, graph);
250+ if (ret != SUCCESS) {
251+ printf("%s - ERROR - [XIR]: Create op in graph failed\n", GetTime().c_str());
252+ GEFinalize();
253+ return FAILED;
254+ }
255+ 
256+ if (!inputs.empty() && !outputs.empty()) {
257+ graph.SetInputs(inputs).SetOutputs(outputs);
258+ }
259+ 
260+ map<AscendString, AscendString> buildOptions;
261+ printf("%s - INFO - [XIR]: Start to create ir session using build options\n", GetTime().c_str());
262+ Session *session = new (std::nothrow) Session(buildOptions);
263+ if (session == nullptr) {
264+ printf("%s - ERROR - [XIR]: Create ir session using build options failed\n", GetTime().c_str());
265+ GEFinalize();
266+ return FAILED;
267+ }
268+ 
269+ map<AscendString, AscendString> graphOptions;
270+ uint32_t graphId = 0;
271+ ret = session->AddGraph(graphId, graph, graphOptions);
272+ if (ret != SUCCESS) {
273+ printf("%s - ERROR - [XIR]: Session add ir compute graph failed\n", GetTime().c_str());
274+ delete session;
275+ GEFinalize();
276+ return FAILED;
277+ }
278+ 
279+ string dumpPath = "./dump_inplace_partial_rotary_mul_grad";
280+ aclgrphDumpGraph(graph, dumpPath.c_str(), dumpPath.length());
281+ 
282+ printf("%s - INFO - [XIR]: Start to run ir compute graph\n", GetTime().c_str());
283+ vector<Tensor> output;
284+ ret = session->RunGraph(graphId, input, output);
285+ if (ret != SUCCESS) {
286+ printf("%s - ERROR - [XIR]: Run graph failed\n", GetTime().c_str());
287+ delete session;
288+ GEFinalize();
289+ return FAILED;
290+ }
291+ printf("%s - INFO - [XIR]: Session run ir compute graph success\n", GetTime().c_str());
292+ 
293+ // Dump input/output binaries for quick inspection after standalone execution.
294+ for (size_t i = 0; i < input.size(); ++i) {
295+ string inputFile = "./tc_ge_irrun_test_inplace_partial_rotary_mul_grad_input_" + std::to_string(i) + ".bin";
296+ uint64_t dataSize = static_cast<uint64_t>(input[i].GetTensorDesc().GetShape().GetShapeSize()) *
297+ GetDataTypeSize(input[i].GetTensorDesc().GetDataType());
298+ WriteDataToFile(inputFile, dataSize, input[i].GetData());
299+ }
300+ 
301+ for (size_t i = 0; i < output.size(); ++i) {
302+ string outputFile = "./tc_ge_irrun_test_inplace_partial_rotary_mul_grad_output_" + std::to_string(i) + ".bin";
303+ uint64_t dataSize = static_cast<uint64_t>(output[i].GetTensorDesc().GetShape().GetShapeSize()) *
304+ GetDataTypeSize(output[i].GetTensorDesc().GetDataType());
305+ WriteDataToFile(outputFile, dataSize, output[i].GetData());
306+ 
307+ if (output[i].GetTensorDesc().GetDataType() == DT_FLOAT) {
308+ const float *resultData = reinterpret_cast<const float *>(output[i].GetData());
309+ const int64_t elemNum = output[i].GetTensorDesc().GetShape().GetShapeSize();
310+ for (int64_t j = 0; j < elemNum && j < 16; ++j) {
311+ printf("result[%ld] is: %f\n", j, resultData[j]);
312+ }
313+ }
314+ }
315+ 
316+ AscendString errorMsg = GEGetErrorMsgV2();
317+ std::cout << "Error message: " << errorMsg.GetString() << std::endl;
318+ AscendString warningMsg = GEGetWarningMsgV2();
319+ std::cout << "Warning message: " << warningMsg.GetString() << std::endl;
320+ 
321+ delete session;
322+ ret = GEFinalize();
323+ if (ret != SUCCESS) {
324+ printf("%s - ERROR - [XIR]: Finalize ir graph session failed\n", GetTime().c_str());
325+ return FAILED;
326+ }
327+ printf("%s - INFO - [XIR]: Finalize ir graph session success\n", GetTime().c_str());
328+ return SUCCESS;
329+}