已合并
docs:modify document合入 nn 仓9.0.0 aclnn 英文 #11183
liujing987913创建于 9月24日
docs:modify document合入 nn 仓9.0.0 aclnn 英文 #11183
已合并
liujing987913创建于 9月24日
共 382 个文件变更+181113-1
@@ -0,0 +1,667 @@
1+# aclnnCelu&aclnnInplaceCelu
2+ 
3+[📄 View source code](https://gitcode.com/cann/ops-nn/tree/master/activation/celu_v2)
4+ 
5+## Supported Products
6+ 
7+|Product | Supported |
8+|:-------------------------|:----------:|
9+| Ascend 950PR/Ascend 950DT | × |
10+| <term>Atlas A3 training products/Atlas A3 inference products</term> | √ |
11+| <term>Atlas A2 training products/Atlas A2 inference products</term> | √ |
12+| <term>Atlas 200I/500 A2 inference products</term> | × |
13+| <term>Atlas inference products</term> | × |
14+| <term>Atlas training products</term> | √ |
15+ 
16+## Function
17+ 
18+- Description: **aclnnCelu** applies the Continuously Differentiable Exponential Linear Unit (CELU) function for each element **x** in the input tensor **self**, and stores the obtained result in **out**. **aclnnInplaceCelu** applies the CELU function for each element **x** in the input tensor **selfRef**, and stores the obtained result in **selfRef**.
19+ 
20+- Formula:
21+ 
22+$$
23+CELU(x) = max(0, x) + min(0, \alpha \ast (exp(x / \alpha) - 1))
24+$$
25+ 
26+## Prototype
27+ 
28+- **aclnnCelu** and **aclnnInplaceCelu** implement the same function in different ways. Select a proper operator based on your requirements.
29+ 
30+ - **aclnnCelu**: An output tensor object needs to be created to store the computation result.
31+ - **aclnnInplaceCelu**: No output tensor object needs to be created, and the computation result is stored in the memory of the input tensor.
32+ 
33+- Each operator has [two-phase API](../../../docs/en/context/two_phase_api.md) calls. First, **aclnnCeluGetWorkspaceSize** or **aclnnInplaceCeluGetWorkspaceSize** is called to obtain the workspace size required for computation and the executor that contains the operator computation process. Then, **aclnnCelu** or **aclnnInplaceCelu** is called to perform computation.
34+ 
35+```Cpp
36+aclnnStatus aclnnCeluGetWorkspaceSize(
37+ const aclTensor* self,
38+ const aclScalar* alpha,
39+ aclTensor* out,
40+ uint64_t* workspaceSize,
41+ aclOpExecutor** executor)
42+```
43+ 
44+```Cpp
45+aclnnStatus aclnnCelu(
46+ void* workspace,
47+ uint64_t workspaceSize,
48+ aclOpExecutor* executor,
49+ aclrtStream stream)
50+```
51+ 
52+```Cpp
53+aclnnStatus aclnnInplaceCeluGetWorkspaceSize(
54+ aclTensor* selfRef,
55+ const aclScalar* alpha,
56+ uint64_t* workspaceSize,
57+ aclOpExecutor** executor)
58+```
59+ 
60+```Cpp
61+aclnnStatus aclnnInplaceCelu(
62+ void* workspace,
63+ uint64_t workspaceSize,
64+ aclOpExecutor* executor,
65+ aclrtStream stream)
66+```
67+ 
68+## aclnnCeluGetWorkspaceSize
69+ 
70+- **Parameters:**
71+
72+ <table style="undefined;table-layout: fixed; width: 1370px"><colgroup>
73+ <col style="width: 271px">
74+ <col style="width: 115px">
75+ <col style="width: 220px">
76+ <col style="width: 200px">
77+ <col style="width: 177px">
78+ <col style="width: 104px">
79+ <col style="width: 138px">
80+ <col style="width: 145px">
81+ </colgroup>
82+ <thead>
83+ <tr>
84+ <th>Name</th>
85+ <th>Input/Output</th>
86+ <th>Description</th>
87+ <th>Precaution</th>
88+ <th>Data Type</th>
89+ <th>Data Format</th>
90+ <th>Dimension (Shape)</th>
91+ <th>Non-contiguous Tensor</th>
92+ </tr></thead>
93+ <tbody>
94+ <tr>
95+ <td>self (aclTensor*) </td>
96+ <td>Input</td>
97+ <td>Input of the CELU activation function, corresponding to x in the formula.</td>
98+ <td>Empty tensors are supported.</td>
99+ <td>FLOAT, FLOAT16, BFLOAT16</td>
100+ <td>ND</td>
@@ -0,0 +1,475 @@
1+# aclnnClippedSwiglu
2+ 
3+[📄 View source code](https://gitcode.com/cann/ops-nn/tree/master/activation/clipped_swiglu)
4+ 
5+## Product Support
6+ 
7+|Product | Supported |
8+|:-------------------------|:----------:|
9+| Ascend 950PR/Ascend 950DT | × |
10+| <term>Atlas A3 training products/Atlas A3 inference products</term> | √ |
11+| <term>Atlas A2 training products/Atlas A2 inference products</term> | √ |
12+| <term>Atlas 200I/500 A2 inference products</term> | × |
13+| <term>Atlas inference products</term> | × |
14+| <term>Atlas training products</term> | × |
15+ 
16+## Function
17+ 
18+- Description: Serves as a clipped Swish-gated linear unit (SwiGLU) activation function that computes the clipped SwiGLU of input tensor x. Compared with **aclnnSwiGlu**, this API introduces additional parameters — **groupIndex**, **alpha**, **limit**, **bias**, and **interleaved** — to support the SwiGLU variant used in GPT-OSS models and grouped scenarios in MoE models.
19+ 
20+- Formula:
21+ 
22+ For a given input tensor **x** with shape [a,b,c,d,e,f,g…], **aclnnClippedSwiglu** performs the following operations:
23+ 
24+ 1. The x is combined along the axis specified by the input parameter dim. The dimension after combination is [pre, cut, after]. The `cut` axis represents the axis that needs to be split into two tensors, following either front-back splitting or odd-even splitting. The dimensions of `pre` and `after` can equal 1. For example, when dim is 3, the dimension of x after combination is [a*b*c, d, e*f*g*...]. Since elements along the **after** axis are contiguous and operations are element-wise, the **cut** and **after** axes are further merged, resulting in a final shape of **[pre,cut]**.
25+ 
26+ 2. Filter the **pre** axis of **x** based on the input parameter **group_index** using the following formula:
27+ 
28+ $$
29+ sum = \text{Sum}(group\_index)
30+ $$
31+ 
32+ $$
33+ x = x[ : sum, : ]
34+ $$
35+ 
36+ Where **sum** is the sum of all elements in **group_index**. This step is skipped when **group_index** is not provided.
37+ 
38+ 3. Split **x** based on the input parameter **interleaved** using the following formula:
39+ 
40+ When **interleaved** is set to **true**, it indicates odd-even split:
41+ 
42+ $$
43+ A = x[ : , : : 2]
44+ $$
45+ 
46+ $$
47+ B = x[ : , 1 : : 2]
48+ $$
49+ 
50+ When **interleaved** is set to **false**, it indicates front-back split:
51+ 
52+ $$
53+ h = x.shape[1] // 2
54+ $$
55+ 
56+ $$
57+ A = x[ : , : h]
58+ $$
59+ 
60+ $$
61+ B = x[ : , h : ]
62+ $$
63+ 4. Compute the clipped SwiGLU variant based on the input parameters **alpha**, **limit**, and **bias** using the following formula:
64+ 
65+ $$
66+ A = A.clamp(min=None, max=limit)
67+ $$
68+ 
69+ $$
70+ B = B.clamp(min=-limit, max=limit)
71+ $$
72+ 
73+ $$
74+ y\_glu = A * sigmoid(alpha * A)
75+ $$
76+ 
77+ $$
78+ y = y\_glu * (B + bias)
79+ $$
80+ 5. Reshape the output tensor **y** to match the original number of dimensions of **x**. The size along the **dim** axis is half that of **x**, while all other dimensions remain the same as **x**.
81+ 
82+## Prototype
83+ 
84+Each operator has [two-phase API](../../../docs/en/context/two_phase_api.md) calls. First, **aclnnClippedSwigluGetWorkspaceSize** is called to obtain the workspace size required for computation and the executor that contains the operator computation flow. Then, **aclnnClippedSwiglu** is called to perform computation.
85+ 
86+```Cpp
87+aclnnStatus aclnnClippedSwigluGetWorkspaceSize(
88+ const aclTensor *x,
89+ const aclTensor *groupIndexOptional,
90+ int64_t dim,
91+ double alpha,
92+ double limit,
93+ double bias,
94+ bool interleaved,
95+ const aclTensor *out,
96+ uint64_t *workspaceSize,
97+ aclOpExecutor **executor)
98+```
99+ 
100+```Cpp
101+aclnnStatus aclnnClippedSwiglu(
102+ void *workspace,
103+ uint64_t workspaceSize,
104+ aclOpExecutor *executor,
105+ aclrtStream stream)
106+```
107+ 
108+## aclnnClippedSwigluGetWorkspaceSize
109+ 
110+- **Parameters**
111+ <table style="undefined;table-layout: fixed; width: 1567px"><colgroup>
112+ <col style="width: 270px">
113+ <col style="width: 120px">
114+ <col style="width: 300px">
115+ <col style="width: 330px">
116+ <col style="width: 212px">
117+ <col style="width: 100px">
118+ <col style="width: 90px">
119+ <col style="width: 145px">
120+ </colgroup>
121+ <thead>
122+ <tr>
123+ <th>Name</th>
124+ <th>Input/Output</th>
125+ <th>Description</th>
126+ <th>Usage Notes</th>
127+ <th>Data Type</th>
128+ <th>Data Format</th>
129+ <th>Shape</th>
130+ <th>Non-contiguous Tensor</th>
131+ </tr></thead>
132+ <tbody>
133+ <tr>
134+ <td>x (aclTensor*) </td>
135+ <td>Input</td>
136+ <td>x in the formula.</td>
137+ <td>Null pointers are not supported. The dimension must be greater than 0, and the shape must be an even number in the dimension corresponding to the input parameter dim.</td>
138+ <td>FLOAT, FLOAT16, BFLOAT16</td>
139+ <td>ND</td>
140+ <td>1-8</td>
141+ <td>-</td>
142+ </tr>
143+ <tr>
144+ <td>groupIndexOptional (aclTensor*) </td>
145+ <td>Input</td>
146+ <td>group_index in the formula, indicating how the input is grouped.</td>
147+ <td>Null pointers are supported. If the pointer is not null, the tensor must be a 1D tensor with non-negative elements. The i-th element indicates the batch size of x to be processed for the i-th group.</td>
148+ <td>INT64</td>
149+ <td>ND</td>
150+ <td>1</td>
151+ <td>-</td>
152+ </tr>
153+ <tr>
154+ <td>dim (int64_t) </td>
155+ <td>Input</td>
156+ <td>dim in the formula, indicating the dimension index used to merge and split tensor x.</td>
157+ <td>The value range is [–x.dim(), x.dim() – 1].</td>
158+ <td>-</td>
159+ <td>-</td>
160+ <td>-</td>
161+ <td>-</td>
162+ </tr>
163+ <tr>
164+ <td>alpha (double) </td>
165+ <td>Input</td>
166+ <td>alpha in the formula, indicating the scaling factor used in the variant SwiGLU computation.</td>
167+ <td>The recommended value is 1.702.</td>
168+ <td>-</td>
169+ <td>-</td>
170+ <td>-</td>
171+ <td>-</td>
172+ </tr>
173+ <tr>
174+ <td>limit (double) </td>
175+ <td>Input</td>
176+ <td>limit in the formula, indicating the clipping threshold used in the variant SwiGLU computation.</td>
177+ <td>The recommended value is 7.0.</td>
178+ <td>-</td>
179+ <td>-</td>
180+ <td>-</td>
181+ <td>-</td>
182+ </tr>
183+ <tr>
184+ <td>bias (double) </td>
185+ <td>Input</td>
186+ <td>bias in the formula, indicating the bias parameter used in the variant SwiGLU computation.</td>
187+ <td>The recommended value is 1.0.</td>
188+ <td>-</td>
189+ <td>-</td>
190+ <td>-</td>
191+ <td>-</td>
192+ </tr>
193+ <tr>
194+ <td>interleaved (bool) </td>
195+ <td>Input</td>
196+ <td>interleaved in the formula, specifying the split mode for x.</td>
197+ <td>true: even-odd split; false: front-back split.</td>
198+ <td>-</td>
199+ <td>-</td>
200+ <td>-</td>
201+ <td>-</td>
202+ </tr>
203+ <tr>
204+ <td>out (aclTensor*) </td>
205+ <td>Output</td>
206+ <td>y in the formula.</td>
207+ <td>Null pointers are not supported. The shape is half of x in the dimension corresponding to the input parameter dim, and is the same as that of x in other dimensions.</td>
208+ <td>FLOAT, FLOAT16, BFLOAT16</td>
209+ <td>ND</td>
210+ <td>1-8</td>
211+ <td>-</td>
212+ </tr>
213+ <tr>
214+ <td>workspaceSize (uint64_t*) </td>
215+ <td>Output</td>
216+ <td>Size of the workspace to be allocated on the device.</td>
217+ <td>-</td>
218+ <td>-</td>
219+ <td>-</td>
220+ <td>-</td>
221+ <td>-</td>
222+ </tr>
223+ <tr>
224+ <td>executor (aclOpExecutor**) </td>
225+ <td>Output</td>
226+ <td>Operator executor, containing the operator computation flow.</td>
227+ <td>-</td>
228+ <td>-</td>
229+ <td>-</td>
230+ <td>-</td>
231+ <td>-</td>
232+ </tr>
233+ </tbody>
234+ </table>
235+ 
236+- **Returns**
237+ 
238+ `aclnnStatus`: status code. For details, see aclnn Return Cod](../../../docs/en/context/aclnn_return_code.md).
239+ 
240+ The first-phase API implements input parameter verification. The following errors may be thrown.
241+ 
242+ <table style="undefined;table-layout: fixed;width: 979px"><colgroup>
243+ <col style="width: 272px">
244+ <col style="width: 103px">
245+ <col style="width: 604px">
246+ </colgroup>
247+ <thead>
248+ <tr>
249+ <th>Return code</th>
250+ <th>Error Code</th>
251+ <th>Description</th>
252+ </tr>
253+ </thead>
254+ <tbody>
255+ <tr>
256+ <td>ACLNN_ERR_PARAM_NULLPTR</td>
257+ <td>161001</td>
258+ <td>The passed x or y is a null pointer.</td>
259+ </tr>
260+ <tr>
261+ <td rowspan="8">ACLNN_ERR_PARAM_INVALID</td>
262+ <td rowspan="8">161002</td>
263+ <td>The input or output data type is not supported.</td>
264+ </tr>
265+ <tr>
266+ <td>The input or output tensor rank is not supported.</td>
267+ </tr>
268+ <tr>
269+ <td>dim is out of the valid range.</td>
270+ </tr>
271+ </tbody>
272+ </table>
273+ 
274+## aclnnClippedSwiglu
275+ 
276+- **Parameters**
277+ <table style="undefined;table-layout: fixed; width: 953px"><colgroup>
278+ <col style="width: 173px">
279+ <col style="width: 112px">
280+ <col style="width: 668px">
281+ </colgroup>
282+ <thead>
283+ <tr>
284+ <th>Name</th>
285+ <th>Input/Output</th>
286+ <th>Description</th>
287+ </tr></thead>
288+ <tbody>
289+ <tr>
290+ <td>workspace</td>
291+ <td>Input</td>
292+ <td>Address of the workspace to be allocated on the device.</td>
293+ </tr>
294+ <tr>
295+ <td>workspaceSize</td>
296+ <td>Input</td>
297+ <td>Size of the workspace to be allocated on the device, obtained by calling the first-phase API aclnnClippedSwigluGetWorkspaceSize.</td>
298+ </tr>
299+ <tr>
300+ <td>executor</td>
301+ <td>Input</td>
302+ <td>Operator executor, containing the operator computation flow.</td>
303+ </tr>
304+ <tr>
305+ <td>stream</td>
306+ <td>Input</td>
307+ <td>Stream for executing the task.</td>
308+ </tr>
309+ </tbody>
310+ </table>
311+ 
312+- **Returns**
313+ 
314+ `aclnnStatus`: status code. For details, see aclnn Return Cod](../../../docs/en/context/aclnn_return_code.md).
315+ 
316+## Constraints
317+ 
318+Deterministic computation: **aclnnClippedSwiglu** defaults to a deterministic implementation. The non-deterministic implementation is not supported, and configuration changes via deterministic computation settings will not take effect.
319+ 
320+## Example
321+ 
322+The following example is for reference only. For details, see [Compile and Run Sample](../../../docs/en/context/compile_and_run_sample.md).
323+ 
324+```Cpp
325+#include <iostream>
326+#include <vector>
327+#include "acl/acl.h"
328+#include "aclnnop/aclnn_clipped_swiglu.h"
329+ 
330+#define CHECK_RET(cond, return_expr) \
331+ do { \
332+ if (!(cond)) { \
333+ return_expr; \
334+ } \
335+ } while (0)
336+ 
337+#define LOG_PRINT(message, ...) \
338+ do { \
339+ printf(message, ##__VA_ARGS__); \
340+ } while (0)
341+ 
342+int64_t GetShapeSize(const std::vector<int64_t>& shape)
343+{
344+ int64_t shapeSize = 1;
345+ for (auto i : shape) {
346+ shapeSize *= i;
347+ }
348+ return shapeSize;
349+}
350+ 
351+int Init(int32_t deviceId, aclrtStream* stream)
352+{
353+ // (Boilerplate) Initialize ACL.
354+ auto ret = aclInit(nullptr);
355+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret);
356+ ret = aclrtSetDevice(deviceId);
357+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret);
358+ ret = aclrtCreateStream(stream);
359+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret);
360+ return 0;
361+}
362+ 
363+template <typename T>
364+int CreateAclTensor(
365+ const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, aclDataType dataType,
366+ aclTensor** tensor)
367+{
368+ auto size = GetShapeSize(shape) * sizeof(T);
369+ // Call aclrtMalloc to allocate memory on the device.
370+ auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST);
371+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret);
372+ // Call aclrtMemcpy to copy the data on the host to the memory on the device.
373+ ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE);
374+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret);
375+ 
376+ // Calculate the strides of the contiguous tensor.
377+ std::vector<int64_t> strides(shape.size(), 1);
378+ for (int64_t i = shape.size() - 2; i >= 0; i--) {
379+ strides[i] = shape[i + 1] * strides[i + 1];
380+ }
381+ 
382+ // Call aclCreateTensor to create an aclTensor.
383+ *tensor = aclCreateTensor(
384+ shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, shape.data(), shape.size(),
385+ *deviceAddr);
386+ return 0;
387+}
388+ 
389+int main()
390+{
391+ // 1. (Boilerplate) Initialize the device and stream. For details, see the ACL API manual.
392+ // Set the device ID (deviceId) based on the actual device.
393+ int32_t deviceId = 0;
394+ aclrtStream stream;
395+ auto ret = Init(deviceId, &stream);
396+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret);
397+ 
398+ // 2. Construct inputs and outputs based on API definitions.
399+ std::vector<int64_t> xShape = {2, 32};
400+ std::vector<int64_t> groupIndexShape = {1};
401+ std::vector<int64_t> outShape = {2, 16};
402+ void* xDeviceAddr = nullptr;
403+ void* groupIndexDeviceAddr = nullptr;
404+ void* outDeviceAddr = nullptr;
405+ aclTensor* x = nullptr;
406+ aclTensor* groupIndex = nullptr;
407+ aclTensor* out = nullptr;
408+ std::vector<float> xHostData = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
409+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
410+ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63};
411+ std::vector<int64_t> groupIndexData = {1};
412+ std::vector<float> outHostData = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
413+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
414+ 
415+ int dim = -1;
416+ float alpha = 1.0;
417+ float limit = 7.0;
418+ float bias = 1.702;
419+ bool interleaved = true;
420+ // Create an x aclTensor.
421+ ret = CreateAclTensor(xHostData, xShape, &xDeviceAddr, aclDataType::ACL_FLOAT, &x);
422+ CHECK_RET(ret == ACL_SUCCESS, return ret);
423+ // Create a groupIndex aclTensor.
424+ ret = CreateAclTensor(groupIndexData, groupIndexShape, &groupIndexDeviceAddr, aclDataType::ACL_INT64, &groupIndex);
425+ // Create an out aclTensor.
426+ ret = CreateAclTensor(outHostData, outShape, &outDeviceAddr, aclDataType::ACL_FLOAT, &out);
427+ CHECK_RET(ret == ACL_SUCCESS, return ret);
428+ // 3. Call the CANN operator library API. Modify the API as required.
429+ uint64_t workspaceSize = 0;
430+ aclOpExecutor* executor;
431+ // Call the first-phase API of aclnnClippedSwiglu.
432+ ret = aclnnClippedSwigluGetWorkspaceSize(
433+ x, groupIndex, dim, alpha, limit, bias, interleaved, out, &workspaceSize, &executor);
434+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnClippedSwigluGetWorkspaceSize failed. ERROR: %d\n", ret); return ret);
435+ // Allocate device memory based on workspaceSize computed by the first-phase API.
436+ void* workspaceAddr = nullptr;
437+ if (workspaceSize > 0) {
438+ ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST);
439+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret);
440+ }
441+ // Call the second-phase API of aclnnClippedSwiglu.
442+ ret = aclnnClippedSwiglu(workspaceAddr, workspaceSize, executor, stream);
443+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnClippedSwiglu failed. ERROR: %d\n", ret); return ret);
444+ 
445+ // 4. (Boilerplate) Synchronize the stream and wait for task completion.
446+ ret = aclrtSynchronizeStream(stream);
447+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret);
448+ 
449+ // 5. Obtain the output value and copy the result from the device to the host. Modify the code based on the API definition.
450+ auto size = GetShapeSize(outShape);
451+ std::vector<float> resultData(size, 0);
452+ ret = aclrtMemcpy(
453+ resultData.data(), resultData.size() * sizeof(resultData[0]), outDeviceAddr, size * sizeof(resultData[0]),
454+ ACL_MEMCPY_DEVICE_TO_HOST);
455+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret);
456+ for (int64_t i = 0; i < size; i++) {
457+ LOG_PRINT("result[%ld] is: %f\n", i, resultData[i]);
458+ }
459+ // 6. Destroy aclTensor and aclScalar. Modify the code based on the API definition.
460+ aclDestroyTensor(x);
461+ aclDestroyTensor(groupIndex);
462+ aclDestroyTensor(out);
463+ // 7. Release device resources. Modify the code based on the API definition.
464+ aclrtFree(xDeviceAddr);
465+ aclrtFree(groupIndexDeviceAddr);
466+ aclrtFree(outDeviceAddr);
467+ if (workspaceSize > 0) {
468+ aclrtFree(workspaceAddr);
469+ }
470+ aclrtDestroyStream(stream);
471+ aclrtResetDevice(deviceId);
472+ aclFinalize();
473+ return 0;
474+}
475+```
@@ -0,0 +1,452 @@
1+# aclnnEluBackward
2+ 
3+[📄 View source code](https://gitcode.com/cann/ops-nn/tree/master/activation/elu_grad_v2)
4+ 
5+## Product Support
6+ 
7+|Product | Supported |
8+|:-------------------------|:----------:|
9+| Ascend 950PR/Ascend 950DT | √ |
10+| <term>Atlas A3 training products/Atlas A3 inference products</term> | √ |
11+| <term>Atlas A2 training products/Atlas A2 inference products</term> | √ |
12+| <term>Atlas 200I/500 A2 inference products</term> | × |
13+| <term>Atlas inference products</term> | √ |
14+| <term>Atlas training products</term> | √ |
15+ 
16+## Function
17+ 
18+- Description: Performs backward computation of the [aclnnElu](../../elu/docs/aclnnElu&aclnnInplaceElu_en.md) activation function and outputs the gradient of the forward input of the ELU activation function.
19+ 
20+- Formula: **x** denotes an element in **selfOrResult**.
21+ 
22+ - When **isResult** is **True**:
23+ 
24+ $$
25+ gradInput = gradOutput *
26+ \begin{cases}
27+ scale, \quad x > 0\\
28+ inputScale \ast (x + \alpha \ast scale), \quad x \leq 0
29+ \end{cases}
30+ $$
31+ 
32+ - When **isResult** is **False**:
33+ 
34+ $$
35+ gradInput = gradOutput *
36+ \begin{cases}
37+ scale, \quad x > 0\\
38+ inputScale \ast \alpha \ast scale \ast exp(x \ast inputScale), \quad x \leq 0
39+ \end{cases}
40+ $$
41+ 
42+## Prototype
43+ 
44+Each operator has [two-phase API](../../../docs/en/context/two_phase_api.md) calls. First, **aclnnEluBackwardGetWorkspaceSize** is called to obtain the workspace size required for computation and the executor that contains the operator computation flow. Then, **aclnnEluBackward** is called to perform computation.
45+ 
46+```Cpp
47+aclnnStatus aclnnEluBackwardGetWorkspaceSize(
48+ const aclTensor* gradOutput,
49+ const aclScalar* alpha,
50+ const aclScalar* scale,
51+ const aclScalar* inputScale,
52+ bool isResult,
53+ const aclTensor* selfOrResult,
54+ aclTensor* gradInput,
55+ uint64_t* workspaceSize,
56+ aclOpExecutor** executor)
57+```
58+ 
59+```Cpp
60+aclnnStatus aclnnEluBackward(
61+ void* workspace,
62+ uint64_t workspaceSize,
63+ aclOpExecutor* executor,
64+ aclrtStream stream)
65+```
66+ 
67+## aclnnEluBackwardGetWorkspaceSize
68+ 
69+- **Parameters**
70+
71+ <table style="undefined;table-layout: fixed; width: 1370px"><colgroup>
72+ <col style="width: 271px">
73+ <col style="width: 115px">
74+ <col style="width: 220px">
75+ <col style="width: 200px">
76+ <col style="width: 177px">
77+ <col style="width: 104px">
78+ <col style="width: 138px">
79+ <col style="width: 145px">
80+ </colgroup>
81+ <thead>
82+ <tr>
83+ <th>Name</th>
84+ <th>Input/Output</th>
85+ <th>Description</th>
86+ <th>Usage Notes</th>
87+ <th>Data Type</th>
88+ <th>Data Format</th>
89+ <th>Shape</th>
90+ <th>Non-contiguous Tensor</th>
91+ </tr></thead>
92+ <tbody>
93+ <tr>
94+ <td>gradOutput (aclTensor*) </td>
95+ <td>Input</td>
96+ <td>Gradient of the forward output of the ELU activation function, corresponding to gradInput in the formula.</td>
97+ <td>Empty tensors are supported.</td>
98+ <td>FLOAT, FLOAT16, BFLOAT16</td>
99+ <td>ND</td>
100+ <td>0-8</td>
101+ <td>√</td>
102+ </tr>
103+ <tr>
104+ <td>alpha (aclScalar*) </td>
105+ <td>Input</td>
106+ <td>Activation coefficient of the ELU activation function, corresponding to \alpha in the formula.</td>
107+ <td><ul><li>If isResult is true, \alpha must be greater than or equal to 0. </li><li>The data type must be convertible to FLOAT (see <a href="../../../docs/en/context/conversion_relationship.md" target="_blank">conversion relationship</a>).</li></ul></td>
108+ <td>-</td>
109+ <td>-</td>
110+ <td>-</td>
111+ <td>-</td>
112+ </tr>
113+ <tr>
114+ <td>scale (aclScalar*) </td>
115+ <td>Input</td>
116+ <td>Scaling factor of the ELU activation function, corresponding to scale in the formula.</td>
117+ <td>The data type must be convertible to FLOAT (see <a href="../../../docs/en/context/conversion_relationship.md" target="_blank">conversion relationship</a>).</td>
118+ <td>-</td>
119+ <td>-</td>
120+ <td>-</td>
121+ <td>-</td>
122+ </tr>
123+ <tr>
124+ <td>inputScale (aclScalar*) </td>
125+ <td>Input</td>
126+ <td>Input scaling factor of the ELU activation function, corresponding to inputScale in the formula.</td>
127+ <td>The data type must be convertible to FLOAT (see <a href="../../../docs/en/context/conversion_relationship.md" target="_blank">conversion relationship</a>).</td>
128+ <td>-</td>
129+ <td>-</td>
130+ <td>-</td>
131+ <td>-</td>
132+ </tr>
133+ <tr>
134+ <td>isResult (bool) </td>
135+ <td>Input</td>
136+ <td>Whether the input for ELU backward computation is the forward output of the ELU operator.</td>
137+ <td>-</td>
138+ <td>-</td>
139+ <td>-</td>
140+ <td>-</td>
141+ <td>-</td>
142+ </tr>
143+ <tr>
144+ <td>selfOrResult (aclTensor*) </td>
145+ <td>Input</td>
146+ <td><ul><li>Forward output of the ELU activation function when isResult is true. </li><li>Forward input of the ELU activation function when isResult is false.</li></ul></td>
147+ <td><ul><li>The data type must be the same as that of gradOutput. </li><li>The shape must be the same as that of gradOutput. </li><li>Empty tensors are supported.</li></ul></td>
148+ <td>FLOAT, FLOAT16, BFLOAT16</td>
149+ <td>ND</td>
150+ <td>0-8</td>
151+ <td>√</td>
152+ </tr>
153+ <tr>
154+ <td>gradInput (aclTensor*) </td>
155+ <td>Output</td>
156+ <td>Gradient of the forward input of the ELU activation function, that is, the derivative of the input, corresponding to gradOutput in the formula.</td>
157+ <td><ul><li>The data type must be convertible from that of gradOutput (see <a href="../../../docs/en/context/conversion_relationship.md" target="_blank">conversion relationship</a>). </li><li>The shape must be the same as that of gradOutput.</li></ul></td>
158+ <td>FLOAT, FLOAT16, BFLOAT16</td>
159+ <td>ND</td>
160+ <td>0-8</td>
161+ <td>√</td>
162+ </tr>
163+ <tr>
164+ <td>workspaceSize (uint64_t*) </td>
165+ <td>Output</td>
166+ <td>Size of the workspace to be allocated on the device.</td>
167+ <td>-</td>
168+ <td>-</td>
169+ <td>-</td>
170+ <td>-</td>
171+ <td>-</td>
172+ </tr>
173+ <tr>
174+ <td>executor (aclOpExecutor**) </td>
175+ <td>Output</td>
176+ <td>Operator executor, containing the operator computation flow.</td>
177+ <td>-</td>
178+ <td>-</td>
179+ <td>-</td>
180+ <td>-</td>
181+ <td>-</td>
182+ </tr>
183+ </tbody>
184+ </table>
185+ - <term>Atlas inference products</term> and <term>Atlas training products</term>: The data type can be FLOAT or FLOAT16.
186+ 
187+- **Returns**
188+ 
189+ `aclnnStatus`: status code. For details, see [aclnn Return Code](../../../docs/en/context/aclnn_return_code.md).
190+ 
191+ The first-phase API implements input parameter verification. The following errors may be thrown.
192+
193+ <table style="undefined;table-layout: fixed;width: 979px"><colgroup>
194+ <col style="width: 272px">
195+ <col style="width: 103px">
196+ <col style="width: 604px">
197+ </colgroup>
198+ <thead>
199+ <tr>
200+ <th>Return Code</th>
201+ <th>Error Code</th>
202+ <th>Description</th>
203+ </tr>
204+ </thead>
205+ <tbody>
206+ <tr>
207+ <td>ACLNN_ERR_PARAM_NULLPTR</td>
208+ <td>161001</td>
209+ <td>The gradOutput, alpha, scale, inputScale, selfOrResult, or gradInput parameter is a null pointer.</td>
210+ </tr>
211+ <tr>
212+ <td rowspan="8">ACLNN_ERR_PARAM_INVALID</td>
213+ <td rowspan="8">161002</td>
214+ <td>The data type of gradOutput or selfOrResult is not supported.</td>
215+ </tr>
216+ <tr>
217+ <td>The data types of gradOutput and selfOrResult are inconsistent.</td>
218+ </tr>
219+ <tr>
220+ <td>The data type of alpha, scale, or inputScale cannot be converted to FLOAT.</td>
221+ </tr>
222+ <tr>
223+ <td>The data type of gradInput is not convertible from that of gradOutput.</td>
224+ </tr>
225+ <tr>
226+ <td>The shapes of gradOutput, selfOrResult, and gradInput do not match.</td>
227+ </tr>
228+ <tr>
229+ <td>gradOutput, selfOrResult, or gradInput has more than eight dimensions.</td>
230+ </tr>
231+ <tr>
232+ <td>When isResult is set to True, alpha is negative.</td>
233+ </tr>
234+ </tbody></table>
235+ 
236+## aclnnEluBackward
237+ 
238+- **Parameters**
239+ 
240+ <table style="undefined;table-layout: fixed; width: 953px"><colgroup>
241+ <col style="width: 173px">
242+ <col style="width: 112px">
243+ <col style="width: 668px">
244+ </colgroup>
245+ <thead>
246+ <tr>
247+ <th>Name</th>
248+ <th>Input/Output</th>
249+ <th>Description</th>
250+ </tr></thead>
251+ <tbody>
252+ <tr>
253+ <td>workspace</td>
254+ <td>Input</td>
255+ <td>Address of the workspace to be allocated on the device.</td>
256+ </tr>
257+ <tr>
258+ <td>workspaceSize</td>
259+ <td>Input</td>
260+ <td>Size of the workspace to be allocated on the device, which is obtained by calling the first-phase API aclnnEluBackwardGetWorkspaceSize.</td>
261+ </tr>
262+ <tr>
263+ <td>executor</td>
264+ <td>Input</td>
265+ <td>Operator executor, containing the operator computation flow.</td>
266+ </tr>
267+ <tr>
268+ <td>stream</td>
269+ <td>Input</td>
270+ <td>Stream for executing the task.</td>
271+ </tr>
272+ </tbody>
273+ </table>
274+ 
275+- **Returns**
276+ 
277+ `aclnnStatus`: status code. For details, see [aclnn Return Code](../../../docs/en/context/aclnn_return_code.md).
278+ 
279+## Constraints
280+ 
281+- Deterministic computation:
282+ - **aclnnEluBackward** defaults to a deterministic implementation.
283+ 
284+## Example
285+ 
286+The following example is for reference only. For details, see [Compile and Run Sample](../../../docs/en/context/compile_and_run_sample.md).
287+ 
288+```Cpp
289+#include <iostream>
290+#include <vector>
291+#include "acl/acl.h"
292+#include "aclnnop/aclnn_elu_backward.h"
293+ 
294+#define CHECK_RET(cond, return_expr) \
295+ do { \
296+ if (!(cond)) { \
297+ return_expr; \
298+ } \
299+ } while (0)
300+ 
301+#define LOG_PRINT(message, ...) \
302+ do { \
303+ printf(message, ##__VA_ARGS__); \
304+ } while (0)
305+ 
306+int64_t GetShapeSize(const std::vector<int64_t>& shape) {
307+ int64_t shapeSize = 1;
308+ for (auto i : shape) {
309+ shapeSize *= i;
310+ }
311+ return shapeSize;
312+}
313+ 
314+int Init(int32_t deviceId, aclrtStream* stream) {
315+ // (Boilerplate) Initialize resources.
316+ auto ret = aclInit(nullptr);
317+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret);
318+ ret = aclrtSetDevice(deviceId);
319+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret);
320+ ret = aclrtCreateStream(stream);
321+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret);
322+ return 0;
323+}
324+ 
325+template <typename T>
326+int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr,
327+ aclDataType dataType, aclTensor** selfOrResult) {
328+ auto size = GetShapeSize(shape) * sizeof(T);
329+ // Call aclrtMalloc to allocate memory on the device.
330+ auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST);
331+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret);
332+
333+ // Call aclrtMemcpy to copy the data on the host to the memory on the device.
334+ ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE);
335+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret);
336+ 
337+ // Compute the strides of the contiguous selfOrResult.
338+ std::vector<int64_t> strides(shape.size(), 1);
339+ for (int64_t i = shape.size() - 2; i >= 0; i--) {
340+ strides[i] = shape[i + 1] * strides[i + 1];
341+ }
342+ 
343+ // Call aclCreateTensor to create an aclTensor.
344+ *selfOrResult = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND,
345+ shape.data(), shape.size(), *deviceAddr);
346+ return 0;
347+}
348+ 
349+int main() {
350+ // 1. (Fixed writing) Initialize the device and stream. For details, see the ACL API manual.
351+ // Set the device ID (deviceId) based on the actual device.
352+ int32_t deviceId = 0;
353+ aclrtStream stream;
354+ auto ret = Init(deviceId, &stream);
355+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret);
356+ 
357+ // 2. Construct inputs and outputs based on API definitions.
358+ std::vector<int64_t> gradOutputShape = {2, 2};
359+ std::vector<int64_t> selfOrResultShape = {2, 2};
360+ std::vector<int64_t> gradInputShape = {2, 2};
361+ void* gradOutputDeviceAddr = nullptr;
362+ void* selfOrResultDeviceAddr = nullptr;
363+ void* gradInputDeviceAddr = nullptr;
364+ aclTensor* gradOutput = nullptr;
365+ aclScalar* alpha = nullptr;
366+ aclScalar* scale = nullptr;
367+ aclScalar* inputScale = nullptr;
368+ aclTensor* selfOrResult = nullptr;
369+ aclTensor* gradInput = nullptr;
370+ std::vector<float> gradOutputHostData = {-2, -1, 0, 1};
371+ std::vector<float> selfOrResultHostData = {-2, -1, 0, 1};
372+ std::vector<float> gradInputHostData = {0, 0, 0, 0};
373+ float alphaValue = 1.0f;
374+ float scaleValue = 1.0f;
375+ float inputScaleValue = 1.0f;
376+ bool isResult = true;
377+ // Create a gradOutput aclTensor.
378+ ret = CreateAclTensor(gradOutputHostData, gradOutputShape, &gradOutputDeviceAddr, aclDataType::ACL_FLOAT,
379+ &gradOutput);
380+ CHECK_RET(ret == ACL_SUCCESS, return ret);
381+ // Create an alpha aclScalar.
382+ alpha = aclCreateScalar(&alphaValue, aclDataType::ACL_FLOAT);
383+ CHECK_RET(alpha != nullptr, return ret);
384+ // Create a scale aclScalar.
385+ scale = aclCreateScalar(&scaleValue, aclDataType::ACL_FLOAT);
386+ CHECK_RET(scale != nullptr, return ret);
387+ // Create an inputScale aclScalar.
388+ inputScale = aclCreateScalar(&inputScaleValue, aclDataType::ACL_FLOAT);
389+ CHECK_RET(inputScale != nullptr, return ret);
390+ // Create a selfOrResult aclTensor.
391+ ret = CreateAclTensor(selfOrResultHostData, selfOrResultShape, &selfOrResultDeviceAddr, aclDataType::ACL_FLOAT,
392+ &selfOrResult);
393+ CHECK_RET(ret == ACL_SUCCESS, return ret);
394+ // Create a gradInput aclTensor.
395+ ret = CreateAclTensor(gradInputHostData, gradInputShape, &gradInputDeviceAddr, aclDataType::ACL_FLOAT, &gradInput);
396+ CHECK_RET(ret == ACL_SUCCESS, return ret);
397+ 
398+ uint64_t workspaceSize = 0;
399+ aclOpExecutor* executor;
400+ 
401+ // aclnnEluBackward API call example
402+ // 3. Call the CANN operator library API. Modify the API as required.
403+ // Call the first-phase API of aclnnEluBackward.
404+ ret = aclnnEluBackwardGetWorkspaceSize(gradOutput, alpha, scale, inputScale, isResult, selfOrResult, gradInput,
405+ &workspaceSize, &executor);
406+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnEluBackwardGetWorkspaceSize failed. ERROR: %d\n", ret); return ret);
407+ // Allocate device memory based on workspaceSize computed by the first-phase API.
408+ void* workspaceAddr = nullptr;
409+ if (workspaceSize > 0) {
410+ ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST);
411+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret);
412+ }
413+ // Call the second-phase API of aclnnEluBackward.
414+ ret = aclnnEluBackward(workspaceAddr, workspaceSize, executor, stream);
415+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnEluBackward failed. ERROR: %d\n", ret); return ret);
416+ 
417+ // 4. (Boilerplate) Synchronize the stream and wait for task completion.
418+ ret = aclrtSynchronizeStream(stream);
419+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret);
420+ 
421+ // 5. Obtain the output value and copy the result from the device to the host. Modify the code based on the API definition.
422+ auto size = GetShapeSize(gradInputShape);
423+ std::vector<float> resultData(size, 0);
424+ ret = aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), gradInputDeviceAddr,
425+ size * sizeof(resultData[0]), ACL_MEMCPY_DEVICE_TO_HOST);
426+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret);
427+ for (int64_t i = 0; i < size; i++) {
428+ LOG_PRINT("result[%ld] is: %f\n", i, resultData[i]);
429+ }
430+ 
431+ // 6. Destroy aclTensor and aclScalar. Modify the code based on the API definition.
432+ aclDestroyTensor(gradOutput);
433+ aclDestroyScalar(alpha);
434+ aclDestroyScalar(scale);
435+ aclDestroyScalar(inputScale);
436+ aclDestroyTensor(selfOrResult);
437+ aclDestroyTensor(gradInput);
438+ 
439+ // 7. Release device resources. Modify the code based on the API definition.
440+ aclrtFree(gradOutputDeviceAddr);
441+ aclrtFree(selfOrResultDeviceAddr);
442+ aclrtFree(gradInputDeviceAddr);
443+ if (workspaceSize > 0) {
444+ aclrtFree(workspaceAddr);
445+ }
446+ aclrtDestroyStream(stream);
447+ aclrtResetDevice(deviceId);
448+ aclFinalize();
449+
450+ return 0;
451+}
452+```
@@ -0,0 +1,523 @@
1+# aclnnErfinv&aclnnInplaceErfinv
2+ 
3+[📄 View source code](https://gitcode.com/cann/ops-nn/tree/master/activation/erfinv)
4+ 
5+## Supported Products
6+ 
7+|Product | Supported |
8+|:-------------------------|:----------:|
9+| Ascend 950PR/Ascend 950DT | √ |
10+| <term>Atlas A3 training products/Atlas A3 inference products</term> | √ |
11+| <term>Atlas A2 training products/Atlas A2 inference products</term> | √ |
12+| <term>Atlas 200I/500 A2 inference products</term> | × |
13+| <term>Atlas inference products</term> | × |
14+| <term>Atlas training products</term> | √ |
15+ 
16+## Function
17+ 
18+- Function: The erfinv function is the inverse function of the Gaussian error function erf. It returns the quantile of each element in the input tensor in the standard normal distribution function.
19+- Formula:
20+ 
21+ $$
22+ y = erfinv(x) \\
23+ x = erf(y)=\frac{2}{\sqrt{\pi } } \int_{0}^{y} e^{-t^{2} } \mathrm{d}t
24+ $$
25+ 
26+## Prototype
27+ 
28+- **aclnnErfinv** and **aclnnInplaceErfinv** implement the same function. Select the appropriate operator based on actual service scenarios.
29+ - **aclnnErfinv**: An output tensor object must be created to store the computation result.
30+ - **aclnnInplaceErfinv**: No output tensor object needs to be created, and the computation result is stored in the memory of the input tensor.
31+- Each operator has [two-phase API](../../../docs/en/context/two_phase_api.md) calls. First, **aclnnErfinvGetWorkspaceSize** or **aclnnInplaceErfinvGetWorkspaceSize** is called to obtain the workspace size required for computation and the executor that contains the operator computation flow. Then, **aclnnErfinv** or **aclnnInplaceErfinv** is called to perform computation.
32+ 
33+```Cpp
34+aclnnStatus aclnnErfinvGetWorkspaceSize(
35+ const aclTensor* self,
36+ aclTensor* out,
37+ uint64_t* workspaceSize,
38+ aclOpExecutor** executor)
39+```
40+ 
41+```Cpp
42+aclnnStatus aclnnErfinv(
43+ void* workspace,
44+ uint64_t workspaceSize,
45+ aclOpExecutor* executor,
46+ const aclrtStream stream)
47+```
48+ 
49+```Cpp
50+aclnnStatus aclnnInplaceErfinvGetWorkspaceSize(
51+ const aclTensor* selfRef,
52+ uint64_t* workspaceSize,
53+ aclOpExecutor** executor)
54+```
55+ 
56+```Cpp
57+aclnnStatus aclnnInplaceErfinv(
58+ void* workspace,
59+ uint64_t workspaceSize,
60+ aclOpExecutor* executor,
61+ aclrtStream stream)
62+```
63+ 
64+## aclnnErfinvGetWorkspaceSize
65+ 
66+- **Parameters**
67+
68+ <table style="undefined;table-layout: fixed; width: 1370px"><colgroup>
69+ <col style="width: 271px">
70+ <col style="width: 115px">
71+ <col style="width: 220px">
72+ <col style="width: 200px">
73+ <col style="width: 177px">
74+ <col style="width: 104px">
75+ <col style="width: 138px">
76+ <col style="width: 145px">
77+ </colgroup>
78+ <thead>
79+ <tr>
80+ <th>Name</th>
81+ <th>Input/Output</th>
82+ <th>Description</th>
83+ <th>Usage</th>
84+ <th>Data Type</th>
85+ <th>Data Format</th>
86+ <th>Dimension (Shape)</th>
87+ <th>Non-contiguous Tensor</th>
88+ </tr></thead>
89+ <tbody>
90+ <tr>
91+ <td>self (aclTensor*) </td>
92+ <td>Input</td>
93+ <td>Input tensor for erfinv computation. $x$ in the formulas.</td>
94+ <td><ul><li>The shape must be the same as that of out. </li><li>Empty tensors are supported.</li></ul></td>
95+ <td>FLOAT, FLOAT16, BFLOAT16, BOOL, INT8, INT16, INT32, INT64, UINT8</td>
96+ <td>ND</td>
97+ <td>0-8</td>
98+ <td>√</td>
99+ </tr>
100+ <tr>
@@ -0,0 +1,340 @@
1+# aclnnFastGelu
2+ 
3+[📄 View source code](https://gitcode.com/cann/ops-nn/tree/master/activation/fast_gelu)
4+ 
5+## Product Support
6+ 
7+| Product | Supported|
8+| :----------------------------------------------------------- | :------: |
9+| Ascend 950PR/Ascend 950DT | √ |
10+| <term>Atlas A3 training products/Atlas A3 inference products</term> | √ |
11+| <term>Atlas A2 training products/Atlas A2 inference products</term> | √ |
12+| <term>Atlas 200I/500 A2 inference products</term> | × |
13+| <term>Atlas inference products</term> | × |
14+| <term>Atlas training products</term> | × |
15+ 
16+## Function
17+ 
18+Description: Computes the fast Gaussian error linear unit (GELU) activation function.
19+**FastGelu** is defined as follows:
20+ 
21+$$
22+FastGelu(x_i) = \frac {x_i} {1 + e^{-1.702 x_i}}
23+$$
24+ 
25+Where $x_{i}$ is the input element.
26+ 
27+## Prototype
28+ 
29+Each operator has [two-phase API](../../../docs/en/context/two_phase_api.md) calls. First, **aclnnFastGeluGetWorkspaceSize** is called to obtain the workspace size required for computation and the executor that contains the operator computation flow. Then, **aclnnFastGelu** is called to perform computation.
30+ 
31+```Cpp
32+aclnnStatus aclnnFastGeluGetWorkspaceSize(
33+ const aclTensor *self,
34+ aclTensor *out,
35+ uint64_t *workspaceSize,
36+ aclOpExecutor **executor)
37+```
38+ 
39+```Cpp
40+aclnnStatus aclnnFastGelu(
41+ void *workspace,
42+ uint64_t workspaceSize,
43+ aclOpExecutor *executor,
44+ aclrtStream stream)
45+```
46+ 
47+## aclnnFastGeluGetWorkspaceSize
48+ 
49+- **Parameters**
50+ 
51+ <table style="undefined;table-layout: fixed; width: 1420px"><colgroup>
52+ <col style="width: 271px">
53+ <col style="width: 115px">
54+ <col style="width: 220px">
55+ <col style="width: 250px">
56+ <col style="width: 177px">
57+ <col style="width: 104px">
58+ <col style="width: 138px">
59+ <col style="width: 145px">
60+ </colgroup>
61+ <thead>
62+ <tr>
63+ <th>Name</th>
64+ <th>Input/Output</th>
65+ <th>Description</th>
66+ <th>Usage Notes</th>
67+ <th>Data Type</th>
68+ <th>Data Format</th>
69+ <th>Shape</th>
70+ <th>Non-contiguous Tensor</th>
71+ </tr></thead>
72+ <tbody>
73+ <tr>
74+ <td>self (aclTensor*) </td>
75+ <td>Input</td>
76+ <td>Input tensor, corresponding to x_{i} in the formula.</td>
77+ <td><ul><li>The data format must be the same as that of out. </li><li>The shape must be the same as that of out. </li><li>The data type must be the same as that of out.</li></ul></td>
78+ <td>FLOAT16, FLOAT32, BFLOAT16</td>
79+ <td>ND</td>
80+ <td>0–8</td>
81+ <td>√</td>
82+ </tr>
83+ <tr>
84+ <td>out (aclTensor*) </td>
85+ <td>Output</td>
86+ <td>Output tensor, corresponding to FastGelu(x_i) in the formula.</td>
87+ <td><ul><li>The data format must be the same as that of self. </li><li>The shape must be the same as that of self. </li><li>The data format must be the same as that of self.</li></ul></td>
88+ <td>FLOAT16, FLOAT32, BFLOAT16</td>
89+ <td>ND</td>
90+ <td>0–8</td>
91+ <td>√</td>
92+ </tr>
93+ <tr>
94+ <td>workspaceSize (uint64_t*) </td>
95+ <td>Output</td>
96+ <td>Size of the workspace required to be allocated on the device.</td>
97+ <td>-</td>
98+ <td>-</td>
99+ <td>-</td>
100+ <td>-</td>
101+ <td>-</td>
102+ </tr>
103+ <tr>
104+ <td>executor (aclOpExecutor**) </td>
105+ <td>Output</td>
106+ <td>Operator executor, containing the operator computation flow.</td>
107+ <td>-</td>
108+ <td>-</td>
109+ <td>-</td>
110+ <td>-</td>
111+ <td>-</td>
112+ </tr>
113+ </tbody>
114+ </table>
115+
116+- **Returns**
117+ 
118+ `aclnnStatus`: status code. For details, see [aclnn Return Code](../../../docs/en/context/aclnn_return_code.md).
119+ 
120+ The first-phase API implements input parameter verification. The following errors may be thrown.
121+
122+ <table style="undefined;table-layout: fixed;width: 979px"><colgroup>
123+ <col style="width: 272px">
124+ <col style="width: 103px">
125+ <col style="width: 604px">
126+ </colgroup>
127+ <thead>
128+ <tr>
129+ <th>Return Code</th>
130+ <th>Error Code</th>
131+ <th>Description</th>
132+ </tr>
133+ </thead>
134+ <tbody>
135+ <tr>
136+ <td>ACLNN_ERR_PARAM_NULLPTR</td>
137+ <td>161001</td>
138+ <td>self or out is a null pointer.</td>
139+ </tr>
140+ <tr>
141+ <td rowspan="8">ACLNN_ERR_PARAM_INVALID</td>
142+ <td rowspan="8">161002</td>
143+ <td>The data types or data formats of self and out do not match.</td>
144+ </tr>
145+ <tr>
146+ <td>The data type of self or out is not supported.</td>
147+ </tr>
148+ <tr>
149+ <td>The shapes of self and out do not match.</td>
150+ </tr>
151+ <tr>
152+ <td>self has more than 8 dimensions.</td>
153+ </tr>
154+ </tbody></table>
155+ 
156+## aclnnFastGelu
157+ 
158+- **Parameters**
159+ 
160+ <table style="undefined;table-layout: fixed; width: 953px"><colgroup>
161+ <col style="width: 173px">
162+ <col style="width: 112px">
163+ <col style="width: 668px">
164+ </colgroup>
165+ <thead>
166+ <tr>
167+ <th>Name</th>
168+ <th>Input/Output</th>
169+ <th>Description</th>
170+ </tr></thead>
171+ <tbody>
172+ <tr>
173+ <td>workspace</td>
174+ <td>Input</td>
175+ <td>Address of the workspace to be allocated on the device.</td>
176+ </tr>
177+ <tr>
178+ <td>workspaceSize</td>
179+ <td>Input</td>
180+ <td>Size of the workspace to be allocated on the device, which is obtained by calling the first-phase API aclnnFastGeluGetWorkspaceSize.</td>
181+ </tr>
182+ <tr>
183+ <td>executor</td>
184+ <td>Input</td>
185+ <td>Operator executor, containing the operator computation flow.</td>
186+ </tr>
187+ <tr>
188+ <td>stream</td>
189+ <td>Input</td>
190+ <td>Stream for executing the task.</td>
191+ </tr>
192+ </tbody>
193+ </table>
194+ 
195+- **Returns**
196+ 
197+ `aclnnStatus`: status code. For details, see [aclnn Return Code](../../../docs/en/context/aclnn_return_code.md).
198+ 
199+## Constraints
200+ 
201+- Deterministic computation:
202+ - **aclnnFastGelu** defaults to a deterministic implementation.
203+ 
204+## Example
205+ 
206+The following example is for reference only. For details, see [Compile and Run Sample](../../../docs/en/context/compile_and_run_sample.md).
207+ 
208+```Cpp
209+#include <iostream>
210+#include <vector>
211+#include "acl/acl.h"
212+#include "aclnnop/aclnn_fast_gelu.h"
213+ 
214+#define CHECK_RET(cond, return_expr) \
215+ do { \
216+ if (!(cond)) { \
217+ return_expr; \
218+ } \
219+ } while (0)
220+ 
221+#define LOG_PRINT(message, ...) \
222+ do { \
223+ printf(message, ##__VA_ARGS__); \
224+ } while (0)
225+ 
226+int64_t GetShapeSize(const std::vector<int64_t>& shape)
227+{
228+ int64_t shapeSize = 1;
229+ for (auto i : shape) {
230+ shapeSize *= i;
231+ }
232+ return shapeSize;
233+}
234+ 
235+int Init(int32_t deviceId, aclrtStream* stream)
236+{
237+ // (Boilerplate) Initialize resources.
238+ auto ret = aclInit(nullptr);
239+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret);
240+ ret = aclrtSetDevice(deviceId);
241+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret);
242+ ret = aclrtCreateStream(stream);
243+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret);
244+ return 0;
245+}
246+ 
247+template <typename T>
248+int CreateAclTensor(
249+ const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, aclDataType dataType,
250+ aclTensor** tensor)
251+{
252+ auto size = GetShapeSize(shape) * sizeof(T);
253+ // Call aclrtMalloc to allocate memory on the device.
254+ auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST);
255+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret);
256+ // Call aclrtMemcpy to copy the data on the host to the memory on the device.
257+ ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE);
258+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret);
259+ 
260+ // Compute the strides of the contiguous tensor.
261+ std::vector<int64_t> strides(shape.size(), 1);
262+ for (int64_t i = shape.size() - 2; i >= 0; i--) {
263+ strides[i] = shape[i + 1] * strides[i + 1];
264+ }
265+ 
266+ // Call aclCreateTensor to create an aclTensor.
267+ *tensor = aclCreateTensor(
268+ shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, shape.data(), shape.size(),
269+ *deviceAddr);
270+ return 0;
271+}
272+ 
273+int main()
274+{
275+ // 1. (Boilerplate) Initialize the device and stream. For details, see the ACL API manual.
276+ // Set the device ID (deviceId) based on the actual device.
277+ int32_t deviceId = 0;
278+ aclrtStream stream;
279+ auto ret = Init(deviceId, &stream);
280+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret);
281+ // 2. Construct inputs and outputs based on API definitions.
282+ std::vector<int64_t> selfShape = {3, 3};
283+ std::vector<int64_t> outShape = {3, 3};
284+ void* selfDeviceAddr = nullptr;
285+ aclTensor* self = nullptr;
286+ void* outDeviceAddr = nullptr;
287+ aclTensor* out = nullptr;
288+ std::vector<float> selfHostData(9, 0);
289+ std::vector<float> outHostData(9, 0);
290+ // Create self and out aclTensors.
291+ ret = CreateAclTensor(selfHostData, selfShape, &selfDeviceAddr, aclDataType::ACL_FLOAT, &self);
292+ CHECK_RET(ret == ACL_SUCCESS, return ret);
293+ ret = CreateAclTensor(outHostData, outShape, &outDeviceAddr, aclDataType::ACL_FLOAT, &out);
294+ CHECK_RET(ret == ACL_SUCCESS, return ret);
295+ 
296+ // 3. Call the CANN operator library API. Modify the API as required.
297+ uint64_t workspaceSize = 0;
298+ aclOpExecutor* executor;
299+ // Call the first-phase API of aclnnFastGelu.
300+ ret = aclnnFastGeluGetWorkspaceSize(self, out, &workspaceSize, &executor);
301+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnFastGeluGetWorkspaceSize failed. ERROR: %d\n", ret); return ret);
302+ // Allocate device memory based on workspaceSize computed by the first-phase API.
303+ void* workspaceAddr = nullptr;
304+ if (workspaceSize > 0) {
305+ ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST);
306+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret);
307+ }
308+ // Call the second-phase API of aclnnFastGelu.
309+ ret = aclnnFastGelu(workspaceAddr, workspaceSize, executor, stream);
310+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnFastGelu failed. ERROR: %d\n", ret); return ret);
311+ // 4. (Boilerplate) Synchronize the stream and wait for task completion.
312+ ret = aclrtSynchronizeStream(stream);
313+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret);
314+ // 5. Obtain the output value and copy the result from the device to the host. Modify the code based on the API definition.
315+ auto size = GetShapeSize(outShape);
316+ std::vector<float> resultData(size, 0);
317+ ret = aclrtMemcpy(
318+ resultData.data(), resultData.size() * sizeof(resultData[0]), outDeviceAddr, size * sizeof(resultData[0]),
319+ ACL_MEMCPY_DEVICE_TO_HOST);
320+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret);
321+ for (int64_t i = 0; i < size; i++) {
322+ LOG_PRINT("result[%ld] is: %f\n", i, resultData[i]);
323+ }
324+ 
325+ // 6. Destroy aclTensor. Modify the code based on the API definition.
326+ aclDestroyTensor(self);
327+ aclDestroyTensor(out);
328+ 
329+ // 7. Release device resources. Modify the code based on the API definition.
330+ aclrtFree(selfDeviceAddr);
331+ aclrtFree(outDeviceAddr);
332+ if (workspaceSize > 0) {
333+ aclrtFree(workspaceAddr);
334+ }
335+ aclrtDestroyStream(stream);
336+ aclrtResetDevice(deviceId);
337+ aclFinalize();
338+ return 0;
339+}
340+```
@@ -0,0 +1,350 @@
1+# aclnnFastGeluBackward
2+ 
3+[📄 View source code](https://gitcode.com/cann/ops-nn/tree/master/activation/fast_gelu_grad)
4+ 
5+## Product Support
6+ 
7+| Product | Supported|
8+| :----------------------------------------------------------- | :------: |
9+| Ascend 950PR/Ascend 950DT | √ |
10+| <term>Atlas A3 training products/Atlas A3 inference products</term> | √ |
11+| <term>Atlas A2 training products/Atlas A2 inference products</term> | √ |
12+| <term>Atlas 200I/500 A2 inference products</term> | × |
13+| <term>Atlas inference products</term> | × |
14+| <term>Atlas training products</term> | × |
15+ 
16+## Function
17+ 
18+Description: Computes the backward pass of [FastGelu](../../fast_gelu/docs/aclnnFastGelu_en.md).
19+**FastGeluBackward** is defined as follows:
20+ 
21+$$
22+dx = dy * ((\frac{1}{e^{-1.702 x}+1} - 1) * -1.702x + 1) * \frac{1}{(e^{-1.702 x}+1)}
23+$$
24+ 
25+## Prototype
26+ 
27+Each operator has [two-phase API](../../../docs/en/context/two_phase_api.md) calls. First, **aclnnFastGeluBackwardGetWorkspaceSize** is called to obtain the workspace size required for computation and the executor that contains the operator computation flow. Then, **aclnnFastGeluBackward** is called to perform computation.
28+ 
29+```Cpp
30+aclnnStatus aclnnFastGeluBackwardGetWorkspaceSize(
31+ const aclTensor *gradOutput,
32+ const aclTensor *self,
33+ aclTensor *gradInput,
34+ uint64_t *workspaceSize,
35+ aclOpExecutor **executor)
36+```
37+ 
38+```Cpp
39+aclnnStatus aclnnFastGeluBackward(
40+ void *workspace,
41+ uint64_t workspaceSize,
42+ aclOpExecutor *executor,
43+ aclrtStream stream)
44+```
45+ 
46+## aclnnFastGeluBackwardGetWorkspaceSize
47+ 
48+- **Parameters**
49+ 
50+ <table style="undefined;table-layout: fixed; width: 1450px"><colgroup>
51+ <col style="width: 271px">
52+ <col style="width: 115px">
53+ <col style="width: 220px">
54+ <col style="width: 280px">
55+ <col style="width: 177px">
56+ <col style="width: 104px">
57+ <col style="width: 138px">
58+ <col style="width: 145px">
59+ </colgroup>
60+ <thead>
61+ <tr>
62+ <th>Name</th>
63+ <th>Input/Output</th>
64+ <th>Description</th>
65+ <th>Usage Notes</th>
66+ <th>Data Type</th>
67+ <th>Data Format</th>
68+ <th>Shape</th>
69+ <th>Non-contiguous Tensor</th>
70+ </tr></thead>
71+ <tbody>
72+ <tr>
73+ <td>gradOutput (aclTensor*) </td>
74+ <td>Input</td>
75+ <td>Gradient for the backward pass, corresponding to dy in the formula.</td>
76+ <td><ul><li>The data format must be the same as that of self and gradInput. </li><li>The shape must be the same as that of self and gradInput. </li><li>The data type must be the same as that of self and gradInput.</li></ul></td>
77+ <td>FLOAT16, FLOAT32, BFLOAT16</td>
78+ <td>ND</td>
79+ <td>0–8</td>
80+ <td>√</td>
81+ </tr>
82+ <tr>
83+ <td>self (aclTensor*) </td>
84+ <td>Input</td>
85+ <td>Input tensor, corresponding to x in the formula. It is the same as self in the forward pass.</td>
86+ <td><ul><li>The data format must be the same as that of gradOutput and gradInput. </li><li>The shape must be the same as that of gradOutput and gradInput. </li><li>The data type must be the same as that of gradOutput and gradInput.</li></ul></td>
87+ <td>FLOAT16, FLOAT32, BFLOAT16</td>
88+ <td>ND</td>
89+ <td>0–8</td>
90+ <td>√</td>
91+ </tr>
92+ <tr>
93+ <td>gradInput (aclTensor*) </td>
94+ <td>Output</td>
95+ <td>Output tensor, corresponding to dx in the formula.</td>
96+ <td><ul><li>The data format must be the same as that of gradOutput and self. </li><li>The shape must be the same as that of gradOutput and self. </li><li>The data type must be the same as that of gradOutput and self.</li></ul></td>
97+ <td>FLOAT16, FLOAT32, BFLOAT16</td>
98+ <td>ND</td>
99+ <td>0–8</td>
100+ <td>√</td>
101+ </tr>
102+ <tr>
103+ <td>workspaceSize (uint64_t*) </td>
104+ <td>Output</td>
105+ <td>Size of the workspace required to be allocated on the device.</td>
106+ <td>-</td>
107+ <td>-</td>
108+ <td>-</td>
109+ <td>-</td>
110+ <td>-</td>
111+ </tr>
112+ <tr>
113+ <td>executor (aclOpExecutor**) </td>
114+ <td>Output</td>
115+ <td>Operator executor, containing the operator computation flow.</td>
116+ <td>-</td>
117+ <td>-</td>
118+ <td>-</td>
119+ <td>-</td>
120+ <td>-</td>
121+ </tr>
122+ </tbody>
123+ </table>
124+ 
125+- **Returns**
126+ 
127+ `aclnnStatus`: status code. For details, see [aclnn Return Code](../../../docs/en/context/aclnn_return_code.md).
128+ 
129+ The first-phase API implements input parameter verification. The following errors may be thrown.
130+
131+ <table style="undefined;table-layout: fixed;width: 979px"><colgroup>
132+ <col style="width: 272px">
133+ <col style="width: 103px">
134+ <col style="width: 604px">
135+ </colgroup>
136+ <thead>
137+ <tr>
138+ <th>Return Code</th>
139+ <th>Error Code</th>
140+ <th>Description</th>
141+ </tr>
142+ </thead>
143+ <tbody>
144+ <tr>
145+ <td>ACLNN_ERR_PARAM_NULLPTR</td>
146+ <td>161001</td>
147+ <td>gradOutput, self, or gradInput is a null pointer.</td>
148+ </tr>
149+ <tr>
150+ <td rowspan="8">ACLNN_ERR_PARAM_INVALID</td>
151+ <td rowspan="8">161002</td>
152+ <td>The data types or data formats of gradOutput, self, and gradInput do not match.</td>
153+ </tr>
154+ <tr>
155+ <td>The data type of gradInput is not supported.</td>
156+ </tr>
157+ <tr>
158+ <td>The shapes of gradOutput, self, and gradInput do not match.</td>
159+ </tr>
160+ <tr>
161+ <td>self has more than 8 dimensions.</td>
162+ </tr>
163+ </tbody></table>
164+ 
165+## aclnnFastGeluBackward
166+ 
167+- **Parameters**
168+ 
169+ <table style="undefined;table-layout: fixed; width: 953px"><colgroup>
170+ <col style="width: 173px">
171+ <col style="width: 112px">
172+ <col style="width: 668px">
173+ </colgroup>
174+ <thead>
175+ <tr>
176+ <th>Name</th>
177+ <th>Input/Output</th>
178+ <th>Description</th>
179+ </tr></thead>
180+ <tbody>
181+ <tr>
182+ <td>workspace</td>
183+ <td>Input</td>
184+ <td>Address of the workspace to be allocated on the device.</td>
185+ </tr>
186+ <tr>
187+ <td>workspaceSize</td>
188+ <td>Input</td>
189+ <td>Size of the workspace to be allocated on the device, which is obtained by calling the first-phase API aclnnFastGeluBackwardGetWorkspaceSize.</td>
190+ </tr>
191+ <tr>
192+ <td>executor</td>
193+ <td>Input</td>
194+ <td>Operator executor, containing the operator computation flow.</td>
195+ </tr>
196+ <tr>
197+ <td>stream</td>
198+ <td>Input</td>
199+ <td>Stream for executing the task.</td>
200+ </tr>
201+ </tbody>
202+ </table>
203+ 
204+- **Returns**
205+ 
206+ `aclnnStatus`: status code. For details, see [aclnn Return Code](../../../docs/en/context/aclnn_return_code.md).
207+ 
208+## Constraints
209+ 
210+- Deterministic computation:
211+ - **aclnnFastGeluBackward** defaults to a deterministic implementation.
212+ 
213+## Example
214+ 
215+The following example is for reference only. For details, see [Compile and Run Sample](../../../docs/en/context/compile_and_run_sample.md).
216+ 
217+```Cpp
218+#include <iostream>
219+#include <vector>
220+#include "acl/acl.h"
221+#include "aclnnop/aclnn_fast_gelu_backward.h"
222+ 
223+#define CHECK_RET(cond, return_expr) \
224+ do { \
225+ if (!(cond)) { \
226+ return_expr; \
227+ } \
228+ } while (0)
229+ 
230+#define LOG_PRINT(message, ...) \
231+ do { \
232+ printf(message, ##__VA_ARGS__); \
233+ } while (0)
234+ 
235+int64_t GetShapeSize(const std::vector<int64_t>& shape) {
236+ int64_t shapeSize = 1;
237+ for (auto i : shape) {
238+ shapeSize *= i;
239+ }
240+ return shapeSize;
241+}
242+ 
243+int Init(int32_t deviceId, aclrtStream* stream) {
244+ // (Boilerplate) Initialize resources.
245+ auto ret = aclInit(nullptr);
246+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret);
247+ ret = aclrtSetDevice(deviceId);
248+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret);
249+ ret = aclrtCreateStream(stream);
250+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret);
251+ return 0;
252+}
253+ 
254+template <typename T>
255+int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr,
256+ aclDataType dataType, aclTensor** tensor) {
257+ auto size = GetShapeSize(shape) * sizeof(T);
258+ // Call aclrtMalloc to allocate memory on the device.
259+ auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST);
260+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret);
261+ // Call aclrtMemcpy to copy the data on the host to the memory on the device.
262+ ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE);
263+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret);
264+ 
265+ // Compute the strides of the contiguous tensor.
266+ std::vector<int64_t> strides(shape.size(), 1);
267+ for (int64_t i = shape.size() - 2; i >= 0; i--) {
268+ strides[i] = shape[i + 1] * strides[i + 1];
269+ }
270+ 
271+ // Call aclCreateTensor to create an aclTensor.
272+ *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND,
273+ shape.data(), shape.size(), *deviceAddr);
274+ return 0;
275+}
276+ 
277+int main() {
278+ // 1. (Boilerplate) Initialize the device and stream. For details, see the ACL API manual.
279+ // Set the device ID (deviceId) based on the actual device.
280+ int32_t deviceId = 0;
281+ aclrtStream stream;
282+ auto ret = Init(deviceId, &stream);
283+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret);
284+ // 2. Construct inputs and outputs based on API definitions.
285+ std::vector<int64_t> gradOutputShape = {3, 3};
286+ std::vector<int64_t> selfShape = {3, 3};
287+ std::vector<int64_t> gradInputShape = {3, 3};
288+ void* gradOutputDeviceAddr = nullptr;
289+ aclTensor* gradOutput = nullptr;
290+ void* selfDeviceAddr = nullptr;
291+ aclTensor* self = nullptr;
292+ void* gradInputDeviceAddr = nullptr;
293+ aclTensor* gradInput = nullptr;
294+ std::vector<float> gradOutputHostData(9, 0);
295+ std::vector<float> selfHostData(9, 0);
296+ std::vector<float> gradInputHostData(9, 0);
297+ // Create gradOutput, self, and gradInput aclTensors.
298+ ret = CreateAclTensor(gradOutputHostData, selfShape, &gradOutputDeviceAddr, aclDataType::ACL_FLOAT, &gradOutput);
299+ CHECK_RET(ret == ACL_SUCCESS, return ret);
300+ ret = CreateAclTensor(selfHostData, selfShape, &selfDeviceAddr, aclDataType::ACL_FLOAT, &self);
301+ CHECK_RET(ret == ACL_SUCCESS, return ret);
302+ ret = CreateAclTensor(gradInputHostData, gradInputShape, &gradInputDeviceAddr, aclDataType::ACL_FLOAT, &gradInput);
303+ CHECK_RET(ret == ACL_SUCCESS, return ret);
304+ 
305+ // 3. Call the CANN operator library API. Modify the API as required.
306+ uint64_t workspaceSize = 0;
307+ aclOpExecutor* executor;
308+ // Call the first-phase API of aclnnFastGeluBackward.
309+ ret = aclnnFastGeluBackwardGetWorkspaceSize(gradOutput, self, gradInput, &workspaceSize, &executor);
310+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnFastGeluBackwardGetWorkspaceSize failed. ERROR: %d\n", ret); return ret);
311+ // Allocate device memory based on workspaceSize computed by the first-phase API.
312+ void* workspaceAddr = nullptr;
313+ if (workspaceSize > 0) {
314+ ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST);
315+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret);
316+ }
317+ // Call the second-phase API of aclnnFastGeluBackward.
318+ ret = aclnnFastGeluBackward(workspaceAddr, workspaceSize, executor, stream);
319+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnFastGeluBackward failed. ERROR: %d\n", ret); return ret);
320+ // 4. (Boilerplate) Synchronize the stream and wait for task completion.
321+ ret = aclrtSynchronizeStream(stream);
322+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret);
323+ // 5. Obtain the output value and copy the result from the device to the host. Modify the code based on the API definition.
324+ auto size = GetShapeSize(gradInputShape);
325+ std::vector<float> resultData(size, 0);
326+ ret = aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), gradInputDeviceAddr,
327+ size * sizeof(resultData[0]), ACL_MEMCPY_DEVICE_TO_HOST);
328+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret);
329+ for (int64_t i = 0; i < size; i++) {
330+ LOG_PRINT("result[%ld] is: %f\n", i, resultData[i]);
331+ }
332+ 
333+ // 6. Destroy aclTensor. Modify the code based on the API definition.
334+ aclDestroyTensor(gradOutput);
335+ aclDestroyTensor(self);
336+ aclDestroyTensor(gradInput);
337+ 
338+ // 7. Release device resources. Modify the code based on the API definition.
339+ aclrtFree(gradOutputDeviceAddr);
340+ aclrtFree(selfDeviceAddr);
341+ aclrtFree(gradInputDeviceAddr);
342+ if (workspaceSize > 0) {
343+ aclrtFree(workspaceAddr);
344+ }
345+ aclrtDestroyStream(stream);
346+ aclrtResetDevice(deviceId);
347+ aclFinalize();
348+ return 0;
349+}
350+```