aclnnRotaryPositionEmbeddingGrad
Applicable Products
| Product | Supported |
|---|---|
| √ | |
| √ | |
| √ | |
| × | |
| × | |
| × |
Function
Description: Performs the backward propagation of the single-path rotary position embedding aclnnRotaryPositionEmbedding.
Formula:
Taking the list of broadcast axes in the forward computation of rotary position embedding as
dims, the formula can be expressed as follows:Atlas A3 training products/Atlas A3 inference products ,Atlas A2 training products/Atlas A2 inference products
(1) Half mode (mode equals 0):
(2) interleave mode (mode equals 1):
(3) quarter mode (mode equals 2):
(4) interleave-half mode (mode equals 3):
Function Prototype
Each operator is divided into a two-phase API. You must first call the "aclnnRotaryPositionEmbeddingGradGetWorkspaceSize" API to obtain the input parameters and calculate the required workspace size based on the process, and then call the "aclnnRotaryPositionEmbeddingGrad" API to perform the computation.
aclnnStatus aclnnRotaryPositionEmbeddingGradGetWorkspaceSize(
const aclTensor *dy,
const aclTensor *cos,
const aclTensor *sin,
const aclTensor *xOptional,
int64_t mode,
const aclTensor *dxOut,
const aclTensor *dcosOut,
const aclTensor *dsinOut,
uint64_t *workspaceSize,
aclOpExecutor **executor)aclnnStatus aclnnRotaryPositionEmbeddingGrad(
void *workspace,
uint64_t workspaceSize,
aclOpExecutor *executor,
aclrtStream stream)aclnnRotaryPositionEmbeddingGradGetWorkspaceSize
Parameters
Parameter Input/Output Description Instruction Data Type Data Format Dimension (Shape) Non-contiguous Tensor dy Input Derivative of the rotary position embedding forward output y. - BFLOAT16, FLOAT16, FLOAT32 ND 4 √ cos Input cos input for forward computation. Must be consistent with the data type of dy. BFLOAT16, FLOAT16, FLOAT32 ND 4 √ sin Input The sin input of the forward computation. Must have the same data type as dy. BFLOAT16, FLOAT16, FLOAT32 ND 4 √ xOptional Optional input. Input x of the forward computation. When it is a null pointer, dcosOut and dsinOut are not computed. Must be of the same data type as dy. BFLOAT16, FLOAT16, FLOAT32 ND 4 √ mode Input Rotation mode. - INT64 - - - dxOut Output Derivative of the forward computation input x. Same data type as dy. BFLOAT16, FLOAT16, FLOAT32 ND 4 x dcosOut Output Derivative of the forward computation input cos. Valid when xOptional is not empty. Must be the same data type as dy. BFLOAT16, FLOAT16, FLOAT32 ND 4 x dsinOut Output Derivative of the forward computation input sin. Valid only when xOptional is not empty. Must have the same data type as dy. BFLOAT16, FLOAT16, FLOAT32 ND 4 x workspaceSize Output Returns the workspace size to be requested on the Device side. - - - - - executor Output Returns the operator executor, which contains the operator computation flow. - - - - - Constraints on the mode parameter:
Atlas A3 training products/Atlas A3 inference products ,Atlas A2 training products/Atlas A2 inference products : 0=half, 1=interleave.Ascend 950PR/Ascend 950DT : 2=quarter, 3=interleave-half.
Return Value
aclnnStatus: return code. For details, see aclnn Return Code.
The first-phase API performs input parameter validation and returns an error in the following scenarios:
Return Value Error Code Description ACLNN_ERR_PARAM_NULLPTR 161001 The required inputs dy, cos, sin and outputs dxOut, dcosOut, dsinOut are null pointers. ACLNN_ERR_PARAM_INVALID 161002 The data types and formats of the input dy, cos, sin, xOptional and output dxOut, dcosOut, dsinOut are not within the supported range. ACLNN_ERR_INNER_TILING_ERROR 561002 The passed shape parameter does not meet the conditions in the Constraints section. The passed mode parameter is not within the range of 0, 1, 2, or 3.
aclnnRotaryPositionEmbeddingGrad
Parameters
Parameter Input/Output Description workspace Input The workspace memory address requested on the Device side. workspaceSize Input The workspace size requested on the Device side, obtained from the first-phase API aclnnRotaryPositionEmbeddingGradGetWorkspaceSize. executor Input Operator executor, which contains the operator computation flow. stream Input Specifies the stream for task execution. Return Value
aclnnStatus: return code. For details, see aclnn Return Code.
Constraints
Deterministic computation:
aclnnRotaryPositionEmbeddingGrad defaults to a deterministic implementation.
Ascend 950PR/Ascend 950DT :The input tensor x has four dimensions, and the shape constraints for each parameter are described as follows:
The last dimension of input tensors x, cos, sin, and output tensor y must be the same size and less than or equal to 1024. For half, interleave, and interleave-half modes, the last dimension must be divisible by 2. For quarter mode, the last dimension must be divisible by 4.
The shapes of input tensor x and output tensor y must be completely identical.
The shapes of input tensors cos and sin must be completely identical. The shapes of cos and sin must satisfy the broadcast relationship with x, and the broadcast shape must equal the shape of x.
Atlas A3 training products/Atlas A3 inference products ,Atlas A2 training products/Atlas A2 inference products Input tensor dy supports BNSD, BSND, SBND, and TND layouts.
The D dimension size of input tensors dy, cos, sin, xOptional and output tensors dxOut, dcosOut, dsinOut must be the same, satisfying D < 896, and must be a multiple of 2.
The shapes of input tensors dy, xOptional and output tensor dxOut must be completely identical.
The shapes of input tensors cos, sin and output tensors dcosOut, dsinOut must be completely identical, and the shapes of cos and sin must be completely identical.
half mode:
B, N < 1000; when dsin and dcos need to be computed, B * N <= 1024
When dy is BNSD, cos and sin support 11SD, B1SD, BNSD; when cos and sin are B1SD, B < S must be satisfied.
When dy is BSND, cos and sin support 1S1D, BS1D, and BSND; when cos and sin are BS1D, B < S must be satisfied.
When dy is SBND, cos and sin support S11D, SB1D, and SBND.
When dy is TND, cos and sin support T1D and TND.
interleave mode:
B * N < 1000 (N < 1000 when dy is TND).
When dy is BNSD, cos and sin support 11SD.
When dy is BSND, cos and sin support 1S1D.
When dy is SBND, cos and sin support S11D.
When dy is TND, cos and sin support T1D.
Example
The following provides example code for reference only. For details about compilation and running, see Compile and Run Samples.
#include "acl/acl.h"
#include "aclnnop/aclnn_rotary_position_embedding_grad.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::vector<int64_t>& shape)
{
int64_t shape_size = 1;
for (auto i : shape) {
shape_size *= i;
}
return shape_size;
}
int Init(int32_t deviceId, aclrtStream* stream)
{
// Boilerplate: resource initialization.
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::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr,
aclDataType dataType, aclTensor** tensor)
{
auto size = GetShapeSize(shape) * sizeof(T);
// Call aclrtMalloc to apply for device-side memory.
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);
// Call aclrtMemcpy to copy host-side data to device-side memory.
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);
// Calculate the strides of a contiguous tensor.
std::vector<int64_t> strides(shape.size(), 1);
for (int64_t i = shape.size() - 2; i >= 0; i--) {
strides[i] = shape[i + 1] * strides[i + 1];
}
// Call the aclCreateTensor API to create an 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. Boilerplate: device/stream initialization. See the ACL API manual.
// Fill in the deviceId based on your actual device.
int32_t deviceId = 0;
aclrtStream stream;
auto ret = Init(deviceId, &stream);
// Handle the check based on your needs.
CHECK_RET(ret == 0, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret);
// 2. Construct the input and output. Construct them based on the API definition.
std::vector<int64_t> dyShape = {1, 1, 1, 128};
std::vector<int64_t> cosShape = {1, 1, 1, 128};
std::vector<int64_t> sinShape = {1, 1, 1, 128};
std::vector<int64_t> dxOutShape = {1, 1, 1, 128};
int64_t mode = 1;
void* dyDeviceAddr = nullptr;
void* cosDeviceAddr = nullptr;
void* sinDeviceAddr = nullptr;
void* dxOutDeviceAddr = nullptr;
aclTensor* dy = nullptr;
aclTensor* cos = nullptr;
aclTensor* sin = nullptr;
aclTensor* dxOut = nullptr;
aclTensor* dcosOut = nullptr;
aclTensor* dsinOut = nullptr;
std::vector<float> dyHostData = {
74, 54, 84, 125, 23, 78, 37, 72, 27, 98, 34, 107, 29, 23, 54, 60, 70, 49, 119, 54, 29, 54,
41, 99, 27, 62, 5, 46, 108, 39, 24, 123, 33, 82, 6, 40, 88, 24, 6, 116, 38, 119, 110, 5,
30, 79, 87, 18, 29, 100, 90, 24, 21, 93, 63, 68, 34, 112, 119, 48, 74, 43, 85, 64, 14, 49,
128, 59, 18, 37, 123, 76, 14, 63, 10, 39, 107, 124, 79, 16, 17, 76, 80, 47, 90, 41, 58, 82,
75, 80, 69, 37, 74, 36, 54, 26, 32, 54, 13, 100, 105, 15, 13, 69, 122, 26, 94, 59, 29, 14,
60, 8, 24, 17, 45, 33, 107, 122, 63, 111, 75, 128, 68, 31, 105, 6, 82, 99};
std::vector<float> cosHostData = {
41, 37, 17, 25, 49, 25, 22, 24, 110, 120, 107, 3, 82, 66, 75, 86, 85, 115, 110, 56, 52, 39,
86, 23, 36, 71, 20, 73, 113, 25, 114, 56, 125, 80, 95, 82, 31, 63, 99, 62, 23, 55, 30, 99,
42, 121, 15, 24, 97, 87, 81, 67, 43, 21, 13, 9, 33, 29, 117, 10, 114, 61, 98, 15, 78, 108,
48, 97, 1, 3, 78, 109, 57, 46, 47, 56, 50, 66, 81, 77, 17, 128, 68, 121, 47, 91, 114, 125,
51, 108, 31, 15, 47, 78, 109, 115, 113, 26, 53, 97, 1, 111, 103, 58, 106, 68, 11, 104, 22, 79,
61, 127, 86, 39, 33, 123, 102, 39, 64, 41, 119, 120, 61, 29, 94, 68, 36, 12};
std::vector<float> sinHostData = {
46, 56, 56, 101, 66, 10, 96, 16, 86, 57, 102, 66, 12, 105, 76, 58, 90, 6, 79, 128, 126, 82,
41, 3, 45, 7, 66, 4, 46, 22, 31, 26, 37, 63, 97, 84, 91, 90, 47, 77, 90, 34, 41, 83,
91, 108, 120, 13, 90, 32, 85, 37, 119, 31, 51, 82, 122, 125, 7, 116, 121, 108, 38, 56, 100, 20,
97, 119, 10, 4, 53, 13, 46, 82, 103, 119, 124, 80, 23, 67, 78, 56, 119, 122, 40, 58, 128, 27,
30, 52, 71, 42, 123, 69, 4, 5, 116, 97, 38, 107, 8, 4, 65, 120, 40, 22, 60, 44, 48, 66,
68, 125, 4, 93, 112, 112, 113, 90, 94, 23, 104, 39, 85, 84, 64, 128, 96, 119};
std::vector<float> dxOutHostData(128, 0);
// Create the dy aclTensor.
ret = CreateAclTensor(dyHostData, dyShape, &dyDeviceAddr, aclDataType::ACL_FLOAT, &dy);
CHECK_RET(ret == ACL_SUCCESS, return ret);
// Create the cos aclTensor.
ret = CreateAclTensor(cosHostData, cosShape, &cosDeviceAddr, aclDataType::ACL_FLOAT, &cos);
CHECK_RET(ret == ACL_SUCCESS, return ret);
// Create sin aclTensor.
ret = CreateAclTensor(sinHostData, sinShape, &sinDeviceAddr, aclDataType::ACL_FLOAT, &sin);
CHECK_RET(ret == ACL_SUCCESS, return ret);
// Create dxOut aclTensor.
ret = CreateAclTensor(dxOutHostData, dxOutShape, &dxOutDeviceAddr, aclDataType::ACL_FLOAT, &dxOut);
CHECK_RET(ret == ACL_SUCCESS, return ret);
// Create dsinOut and dcosOut.
std::vector<int64_t> emptyTensorOutShape = {1, 1, 1, 0};
std::vector<int64_t> emptyTensorStride(emptyTensorOutShape.size(), 0);
dcosOut = aclCreateTensor(emptyTensorOutShape.data(), emptyTensorOutShape.size(), aclDataType::ACL_FLOAT,
emptyTensorStride.data(), 0, aclFormat::ACL_FORMAT_ND, emptyTensorOutShape.data(),
emptyTensorOutShape.size(), nullptr);
dsinOut = aclCreateTensor(emptyTensorOutShape.data(), emptyTensorOutShape.size(), aclDataType::ACL_FLOAT,
emptyTensorStride.data(), 0, aclFormat::ACL_FORMAT_ND, emptyTensorOutShape.data(),
emptyTensorOutShape.size(), nullptr);
// 3. Call the CANN operator library API. Modify it to the specific API.
uint64_t workspaceSize = 0;
aclOpExecutor* executor;
// Call the first-phase API of aclnnRotaryPositionEmbeddingGrad.
ret = aclnnRotaryPositionEmbeddingGradGetWorkspaceSize(dy, cos, sin, nullptr, mode, dxOut, dcosOut, dsinOut,
&workspaceSize, &executor);
CHECK_RET(ret == ACL_SUCCESS,
LOG_PRINT("aclnnRotaryPositionEmbeddingGradGetWorkspaceSize failed. ERROR: %d\n", ret);
return ret);
// Apply for device memory based on the workspaceSize calculated by the first-phase API.
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;);
}
// Call the second-phase API of aclnnRotaryPositionEmbeddingGrad.
ret = aclnnRotaryPositionEmbeddingGrad(workspaceAddr, workspaceSize, executor, stream);
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnRotaryPositionEmbeddingGrad failed. ERROR: %d\n", ret); return ret);
// 4. Boilerplate: synchronously wait for the task execution to complete.
ret = aclrtSynchronizeStream(stream);
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret);
// 5. Obtain the output value and copy the result from the device-side memory to the host side. Modify based on the specific API definition.
auto size = GetShapeSize(dxOutShape);
std::vector<float> resultData(size, 0);
ret = aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), dxOutDeviceAddr,
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("result[%ld] is: %f\n", i, resultData[i]);
}
// 6. Release aclTensor and aclScalar. Modify based on the specific API definition.
aclDestroyTensor(dy);
aclDestroyTensor(cos);
aclDestroyTensor(sin);
aclDestroyTensor(dxOut);
// 7. Release device resources.
aclrtFree(dyDeviceAddr);
aclrtFree(cosDeviceAddr);
aclrtFree(sinDeviceAddr);
aclrtFree(dxOutDeviceAddr);
if (workspaceSize > 0) {
aclrtFree(workspaceAddr);
}
aclrtDestroyStream(stream);
aclrtResetDevice(deviceId);
aclFinalize();
return 0;
}