aclnnDeepNorm
Applicable Products
| Product | Supported |
|---|---|
| × | |
| √ | |
| √ | |
| × | |
| √ | |
| × |
Function
Description: Performs deep normalization on the elements of the input tensor x by computing its mean and standard deviation, normalizing each element to an output tensor with zero mean and unit variance.
Formula:
Function Prototype
Each operator is divided into a two-phase API. The "aclnnDeepNormGetWorkspaceSize" API must be called first to obtain the workspace size required for computation and the executor that encapsulates the operator computation flow. Then, the "aclnnDeepNorm" API is called to perform the computation.
aclnnStatus aclnnDeepNormGetWorkspaceSize(
const aclTensor *x,
const aclTensor *gx,
const aclTensor *beta,
const aclTensor *gamma,
double alpha,
double epsilon,
const aclTensor *meanOut,
const aclTensor *rstdOut,
const aclTensor *yOut,
uint64_t *workspaceSize,
aclOpExecutor **executor)aclnnStatus aclnnDeepNorm(
void *workspace,
uint64_t workspaceSize,
aclOpExecutor *executor,
aclrtStream stream)aclnnDeepNormGetWorkspaceSize
Parameters
Parameter Input/Output Description Instruction Data Type Data Format Dimension (Shape) Non-contiguous Tensor x (aclTensor*) Input Represents the input data, typically the intermediate layer output of a neural network, corresponding to `x` in the formula. Supports nullable tensors. FLOAT32, FLOAT16, BFLOAT16 ND 2-8 √ gx (aclTensor*) Input Represents the gradient of the input data, used for backward propagation, corresponding to `gx` in the formula. - Nullable support.
- The data type is consistent with that of
x. - The shape has the same dimensions as the input
x.
FLOAT32, FLOAT16, BFLOAT16 ND 2-8 ✓ beta (aclTensor*) Input Represents the bias parameter used to adjust the normalized output, corresponding to `beta` in the formula. - Supports null tensor.
- The data type is consistent with that of `x`.
- The shape has the same dimensions as the last few dimensions of input `x`, which represent the dimensions to be normalized.
FLOAT32, FLOAT16, BFLOAT16 ND 1-7 √ gamma (aclTensor*) Input Represents the scaling parameter for adjustment of the normalized output, corresponding to `gamma` in the formula. - Supports nullable tensors.
- The data type is consistent with that of `x`.
- The shape dimensions are the same as the first few dimensions of the input `x`, where the first few dimensions represent the dimensions to be normalized.
FLOAT32, FLOAT16, BFLOAT16 ND 1-7 √ alpha (double) Input Represents the weight parameter used to adjust the weight of input data, corresponding to `alpha` in the formula. - - - - - epsilon (double) Input Specifies the value added to the variance to prevent division by zero. Corresponds to `epsilon` in the formula. - - - - - meanOut (aclTensor*) Output Represents the computed mean output for normalization, corresponding to `mean` in the formula. - Nullable tensor is supported.
- The shape satisfies the broadcast relationship with the input `x` (the first few dimensions have the same dimension as the first few dimensions of the input `x`, where the first few dimensions represent the dimensions that do not require normalization, and the remaining dimensions have a size of 1).
FLOAT32 ND 2-8 √ rstdOut (aclTensor*) Output Represents the reciprocal of the standard deviation of the computed output, used for normalization and corresponds to `rstd` in the corresponding formula. - Supports nullable tensors.
- The shape satisfies the broadcast relationship with the input `x` (the first few dimensions have the same dimensions as the first few dimensions of the input `x`, where the first few dimensions represent the dimensions that do not require normalization, and the remaining dimensions have a size of 1).
FLOAT32 ND 2-8 √ yOut (aclTensor*) Output Represents the normalized output data, corresponding to `y` in the formula. - Supports nullable tensors.
- The data type remains consistent with the data type of `x`.
- The shape has the same dimensions as the input `x`.
FLOAT32, FLOAT16, BFLOAT16 ND 2-8 √ workspaceSize (uint64_t*) Output Returns the workspace size that the user needs to apply for on the Device side. - - - - - executor (aclOpExecutor**) Output Returns the operator executor, which includes the operator computation flow. - - - - - Atlas training products ,Atlas inference products : The data types of parametersx,gx,beta,gamma, andyOutdo not support BFLOAT16.
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 Code Error Code Description ACLNN_ERR_PARAM_NULLPTR 161001 Indicates that the input parameter is a required input, output, or required attribute, and is a null pointer. ACLNN_ERR_PARAM_INVALID 161002 The data type of the input or output is not within the supported range. The shapes of the input and output do not match or are not within the supported dimension range. The data types of the input and output do not meet the constraints in the parameter description.
aclnnDeepNorm
Parameters
Parameter Input/Output Description workspace Input Address of the workspace memory applied on the Device side. workspaceSize Input Size of the workspace applied on the Device side, obtained from the first-phase API aclnnDeepNormGetWorkspaceSize. executor Input Operator executor that includes the computation flow. stream Input Specifies the stream for task execution. Return Value
aclnnStatus: return code. For details, see aclnn Return Code.
Constraints
Functional dimensions:
Data type support:
Atlas inference products : FLOAT32 and FLOAT16 are supported for x, gx, beta, gamma, and yOut.Atlas A2 training products/Atlas A2 inference products ,Atlas A3 training products/Atlas A3 inference products : FLOAT32, FLOAT16, and BFLOAT16 are supported for x, gx, beta, gamma, and yOut.rstdOut and meanOut support: FLOAT32.
Data format support: ND.
Unsupported type description:
DOUBLE: The instruction does not support DOUBLE.
Boundary value scenario description:
When the input is Inf, the output is Inf.
When the input is NaN, the output is NaN.
Deterministic computation:
- aclnnDeepNorm defaults to a deterministic implementation.
Example
The following provides example code for reference only. For details about compilation and running, see Compile and Run Samples.
#include <iostream>
#include <vector>
#include "acl/acl.h"
#include "aclnnop/aclnn_deep_norm.h"
#define CHECK_RET(cond, return_expr) \
do { \
if (!(cond)) { \
return_expr; \
} \
} while (0)
#define LOG_PRINT(message, ...) \
do { \
printf(message, ##__VA_ARGS__); \
} while (0)
int64_t GetShapeSize(const std::vector<int64_t>& shape)
{
int64_t shapeSize = 1;
for (auto i : shape) {
shapeSize *= i;
}
return shapeSize;
}
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 the 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) Initialize the device/stream. 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 own needs.
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret);
// 2. Construct the input and output. Customize the construction based on the API interface.
float alpha = 0.3;
float eps = 1e-6;
std::vector<int64_t> xShape = {3, 1, 4};
std::vector<int64_t> gxShape = {3, 1, 4};
std::vector<int64_t> betaShape = {4};
std::vector<int64_t> gammaShape = {4};
std::vector<int64_t> outputMeanShape = {3, 1, 1};
std::vector<int64_t> outputRstdShape = {3, 1, 1};
std::vector<int64_t> outputYShape = {3, 1, 4};
void* xDeviceAddr = nullptr;
void* gxDeviceAddr = nullptr;
void* betaDeviceAddr = nullptr;
void* gammaDeviceAddr = nullptr;
void* outputMeanDeviceAddr = nullptr;
void* outputRstdDeviceAddr = nullptr;
void* outputYDeviceAddr = nullptr;
aclTensor* x = nullptr;
aclTensor* gx = nullptr;
aclTensor* beta = nullptr;
aclTensor* gamma = nullptr;
aclTensor* outputMean = nullptr;
aclTensor* outputRstd = nullptr;
aclTensor* outputY = nullptr;
std::vector<float> xHostData = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
std::vector<float> gxHostData = {2, 2, 2, 4, 4, 4, 6, 6, 6, 8, 8, 8};
std::vector<float> betaHostData = {0, 1, 2, 3};
std::vector<float> gammaHostData = {0, 1, 2, 3};
std::vector<float> outputMeanHostData = {0, 1, 2};
std::vector<float> outputRstdHostData = {0, 1, 2};
std::vector<float> outputYHostData = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
// Create the self aclTensor.
ret = CreateAclTensor(xHostData, xShape, &xDeviceAddr, aclDataType::ACL_FLOAT, &x);
CHECK_RET(ret == ACL_SUCCESS, return ret);
ret = CreateAclTensor(gxHostData, gxShape, &gxDeviceAddr, aclDataType::ACL_FLOAT, &gx);
CHECK_RET(ret == ACL_SUCCESS, return ret);
ret = CreateAclTensor(betaHostData, betaShape, &betaDeviceAddr, aclDataType::ACL_FLOAT, &beta);
CHECK_RET(ret == ACL_SUCCESS, return ret);
ret = CreateAclTensor(gammaHostData, gammaShape, &gammaDeviceAddr, aclDataType::ACL_FLOAT, &gamma);
CHECK_RET(ret == ACL_SUCCESS, return ret);
ret = CreateAclTensor(
outputMeanHostData, outputMeanShape, &outputMeanDeviceAddr, aclDataType::ACL_FLOAT, &outputMean);
CHECK_RET(ret == ACL_SUCCESS, return ret);
ret = CreateAclTensor(
outputRstdHostData, outputRstdShape, &outputRstdDeviceAddr, aclDataType::ACL_FLOAT, &outputRstd);
CHECK_RET(ret == ACL_SUCCESS, return ret);
ret = CreateAclTensor(outputYHostData, outputYShape, &outputYDeviceAddr, aclDataType::ACL_FLOAT, &outputY);
CHECK_RET(ret == ACL_SUCCESS, return ret);
uint64_t workspaceSize = 0;
aclOpExecutor* executor;
// Example of calling the aclnnDeepNorm API.
// 3. Call the CANN operator library API. Replace with the specific API name.
// Call the first-phase API of aclnnDeepNorm.
LOG_PRINT("\nUse aclnnDeepNorm Port.");
ret = aclnnDeepNormGetWorkspaceSize(
x, gx, beta, gamma, alpha, eps, outputMean, outputRstd, outputY, &workspaceSize, &executor);
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnDeepNormGetWorkspaceSize 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 aclnnDeepNorm.
ret = aclnnDeepNorm(workspaceAddr, workspaceSize, executor, stream);
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnDeepNorm failed. ERROR: %d\n", ret); return ret);
// 4. (Boilerplate) Synchronize and wait for 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 device-side memory to the host side. Modify based on the specific API definition.
auto outputMeanSize = GetShapeSize(outputMeanShape);
std::vector<float> resultDataMean(outputMeanSize, 0);
ret = aclrtMemcpy(
resultDataMean.data(), resultDataMean.size() * sizeof(resultDataMean[0]), outputMeanDeviceAddr,
outputMeanSize * sizeof(resultDataMean[0]), ACL_MEMCPY_DEVICE_TO_HOST);
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret);
LOG_PRINT("== pdx output");
for (int64_t i = 0; i < outputMeanSize; i++) {
LOG_PRINT("result[%ld] is: %f\n", i, resultDataMean[i]);
}
auto outputRstdSize = GetShapeSize(outputRstdShape);
std::vector<float> resultDataRstd(outputRstdSize, 0);
ret = aclrtMemcpy(
resultDataRstd.data(), resultDataRstd.size() * sizeof(resultDataRstd[0]), outputRstdDeviceAddr,
outputRstdSize * sizeof(resultDataRstd[0]), ACL_MEMCPY_DEVICE_TO_HOST);
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret);
LOG_PRINT("== pdx output");
for (int64_t i = 0; i < outputRstdSize; i++) {
LOG_PRINT("result[%ld] is: %f\n", i, resultDataRstd[i]);
}
auto outputYSize = GetShapeSize(outputYShape);
std::vector<float> resultDataY(outputYSize, 0);
ret = aclrtMemcpy(
resultDataY.data(), resultDataY.size() * sizeof(resultDataY[0]), outputYDeviceAddr,
outputYSize * sizeof(resultDataY[0]), ACL_MEMCPY_DEVICE_TO_HOST);
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret);
LOG_PRINT("== pdx output");
for (int64_t i = 0; i < outputYSize; i++) {
LOG_PRINT("result[%ld] is: %f\n", i, resultDataY[i]);
}
// 6. Release aclTensor and aclScalar. Modify based on the specific API definition.
aclDestroyTensor(x);
aclDestroyTensor(gx);
aclDestroyTensor(beta);
aclDestroyTensor(gamma);
aclDestroyTensor(outputMean);
aclDestroyTensor(outputRstd);
aclDestroyTensor(outputY);
// 7. Release device resources. Modify based on the specific API definition.
aclrtFree(xDeviceAddr);
aclrtFree(gxDeviceAddr);
aclrtFree(gammaDeviceAddr);
aclrtFree(betaDeviceAddr);
aclrtFree(outputMeanDeviceAddr);
aclrtFree(outputRstdDeviceAddr);
aclrtFree(outputYDeviceAddr);
if (workspaceSize > 0) {
aclrtFree(workspaceAddr);
}
aclrtDestroyStream(stream);
aclrtResetDevice(deviceId);
aclFinalize();
return 0;
}