aclnnSilentCheckV2
Applicable Products
| Product | Supported |
|---|---|
| × | |
| √ | |
| √ | |
| × | |
| × | |
| × |
Function
Operator function:
Added the aclnnSilentCheckV2 API. This version changes the computation logic compared with the aclnnSilentCheck API, and compares val with the newly added Markov inequality threshold based on the stepRef parameter for verification.
Formula:
If stepRef==0:
If the current input
valis inf/-inf/nan, orvalexceedsavgRef*cThreshL1, it is identified as an L1 Level Fault, and an ERROR log is printed. If the environment variablenpuAsdDetectis 1,avgRefandstepRefare updated and the function returns normally; otherwise, inputGradRef is set to zero and checkpoint-based training recovery is triggered.If the current input
valexceedsavgRef*cThreshL2, it is identified as an L2 Level Alarm; a WARNING log is printed, andavgRefandstepRefare updated before returning normally.
If stepRef > 0:
If the current input
valis inf/-inf/nan, orvalexceeds the Markov inequality threshold (avgRef/(1-beta1)^stepRef) * cThreshL1, it is identified as an L1 Level Fault, and an ERROR log is printed. If the environment variablenpuAsdDetectis 2, checkpoint-based training recovery is triggered; if the environment variablenpuAsdDetectis 1,avgRefandstepRefare updated and the function returns normally.If the current input
valexceeds the Markov inequality threshold (avgRef/(1-beta1)^stepRef) * cThreshL2, it is identified as an L2 Level Alarm; a WARNING log is printed, andavgRefandstepRefare updated before returning normally.If no L1 Level Fault or L2 Level Alarm is triggered, under normal conditions: if
npuAsdDetectis 3, the characteristic values ofvalare printed; otherwise,avgRefandstepRefare updated and the function returns normally.
stepRefindicates the detection count.
Function Prototype
Each operator is divided into a two-phase API. The "aclnnSilentCheckV2GetWorkspaceSize" API must be called first to obtain the workspace size required for computation and the executor that encapsulates the operator computation flow. Then, the "aclnnSilentCheckV2" API is called to perform the computation.
aclnnStatus aclnnSilentCheckV2GetWorkspaceSize(
const aclTensor *val,
const aclTensor *max,
aclTensor *avgRef,
aclTensor *inputGradRef,
aclTensor *stepRef,
aclIntArray *dstSize,
aclIntArray *dstStride,
aclIntArray *dstOffset,
float cThreshL1,
float cThreshL2,
float beta1,
int32_t npuAsdDetect,
aclTensor* result,
uint64_t *workspaceSize,
aclOpExecutor **executor)aclnnStatus aclnnSilentCheckV2(
void *workspace,
uint64_t workspaceSize,
aclOpExecutor *executor,
aclrtStream stream)aclnnSilentCheckV2GetWorkspaceSize
Parameters:
Parameter Input/Output Description Instruction Data Type Data Format Dimension (Shape) Non-contiguous Tensor val Input The current input value. - FLOAT, FLOAT16, BFLOAT16 ND 1 √ max Input. - - FLOAT, FLOAT16, BFLOAT16 ND 1 √ avgRef Input - - FLOAT, FLOAT16, BFLOAT16 ND 1 √ inputGradRef Input Gradient tensor of the model input. - FLOAT, FLOAT16, BFLOAT16 ND - √ stepRef Input Current step count. Negative numbers are not supported. INT64 ND Must be [1]. √ dstSize Input - - INT64 ND - - dstStride Input - - INT64 ND - - dstOffset Input - - INT64 ND - - cThreshL1 Input Absolute value threshold for triggering an L1 Level Fault. Currently recommended value: 1000000. FLOAT - - - cThreshL2 Input Absolute numeric threshold for triggering an L2 level fault. Currently, the recommended value is 10000, and cThreshL1 > cThreshL2. FLOAT - - - beta1 Input - Currently recommended value is 0.99, with a range of 0 < beta1 < 1. It is recommended that the value be infinitely close to 1. FLOAT - - - npuAsdDetect Input Environment variable. - INT32 - - - result Output Returns the silent check result. - INT32 ND - √ workspaceSize Output Returns the workspace size to be allocated on the Device side. - - - - - executor Output Returns the operator executor, which contains the operator computation flow. - - - - - Return value:
aclnnStatus: return code. For details, see aclnn Return Codes.
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 passed val, max, avgRef, inputGradRef, stepRef, dstSize, dstStride, and dstOffset are null pointers. ACLNN_ERR_PARAM_INVALID 161002 The data type of val, max, avgRef, inputGradRef, stepRef, dstSize, dstStride, or dstOffset is not within the supported range. The shape of val, max, avgRef, inputGradRef, stepRef, dstSize, dstStride, or dstOffset does not meet the requirement. The value of cThreshL1, cThreshL2, or beta1 is not within the supported range.
aclnnSilentCheck
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 aclnnSilentCheckGetWorkspaceSize. executor Input Operator executor that contains the operator computation flow. stream Input Specifies the stream on which the task is executed. Return value:
aclnnStatus: return code. For details, see aclnn Return Codes.
Constraints
Deterministic computation:
- aclnnSilentCheckV2 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_silent_check_v2.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(std::vector<int64_t>& shape) {
int64_t shapeSize = 1;
for (auto i : shape) {
shapeSize *= i;
}
return shapeSize;
}
void PrintOutResult(std::vector<int64_t> &shape, void** deviceAddr) {
auto size = GetShapeSize(shape);
std::vector<int32_t> resultData(size, 0);
auto ret = aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]),
*deviceAddr, size * sizeof(resultData[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);
for (int64_t i = 0; i < size; i++) {
LOG_PRINT("result[%ld] is: %d\n", i, resultData[i]);
}
}
int Init(int32_t deviceId, aclrtStream* stream) {
// Boilerplate for ACL 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(std::vector<T>& hostData, std::vector<int64_t>& shape, void** deviceAddr,
aclDataType dataType, aclTensor** tensor) {
auto size = GetShapeSize(shape) * sizeof(T);
// Call aclrtMalloc to allocate 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) Initialize the device/stream. For details, see the acl external API list.
// Set deviceId based on the actual device.
int32_t deviceId = 0;
aclrtStream stream;
auto ret = Init(deviceId, &stream);
// Handle the check based on your requirements.
CHECK_RET(ret == 0, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret);
// 2. Construct inputs and outputs. Customize the construction based on the API.
std::vector<int64_t> valShape = {1};
std::vector<int64_t> maxShape = {1};
std::vector<int64_t> avgRefShape = {1};
std::vector<int64_t> inputGradRefShape = {2, 3};
std::vector<int64_t> stepRefShape = {1};
std::vector<int64_t> resultShape = {1};
void* valDeviceAddr = nullptr;
void* maxDeviceAddr = nullptr;
void* avgRefDeviceAddr = nullptr;
void* inputGradRefDeviceAddr = nullptr;
void* stepRefDeviceAddr = nullptr;
void* resultDeviceAddr = nullptr;
aclTensor* val = nullptr;
aclTensor* max = nullptr;
aclTensor* avgRef = nullptr;
aclTensor* inputGradRef = nullptr;
aclTensor* stepRef = nullptr;
aclTensor* result = nullptr;
std::vector<float> valHostData = {160.0};
std::vector<float> maxHostData = {400.0};
std::vector<float> avgRefHostData = {200.0};
std::vector<float> inputGradRefHostData = {0, 1, 2, 3, 4, 5};
std::vector<int64_t> stepRefHostData = {0};
std::vector<int64_t> dstSizeData = {2, 3};
std::vector<int64_t> dstStrideData = {3, 1};
std::vector<int64_t> dstOffsetData = {0};
std::vector<int32_t> resultHostData = {0};
aclIntArray* dstSize = aclCreateIntArray(dstSizeData.data(), 2);
aclIntArray* dstStride = aclCreateIntArray(dstStrideData.data(), 2);
aclIntArray* dstOffset = aclCreateIntArray(dstOffsetData.data(), 1);
float cThreshL1 = 1000000;
float cThreshL2 = 10000;
float beta1 = 0.99;
int32_t npuAsdDetect = 3;
// Create the val aclTensor.
ret = CreateAclTensor(valHostData, valShape, &valDeviceAddr, aclDataType::ACL_FLOAT, &val);
CHECK_RET(ret == ACL_SUCCESS, return ret);
// Create the max aclTensor.
ret = CreateAclTensor(maxHostData, maxShape, &maxDeviceAddr, aclDataType::ACL_FLOAT, &max);
CHECK_RET(ret == ACL_SUCCESS, return ret);
// Create the avgRef aclTensor.
ret = CreateAclTensor(avgRefHostData, avgRefShape, &avgRefDeviceAddr, aclDataType::ACL_FLOAT, &avgRef);
CHECK_RET(ret == ACL_SUCCESS, return ret);
// Create the inputGradRef aclTensor.
ret = CreateAclTensor(inputGradRefHostData, inputGradRefShape, &inputGradRefDeviceAddr, aclDataType::ACL_FLOAT, &inputGradRef);
CHECK_RET(ret == ACL_SUCCESS, return ret);
// Create the stepRef aclTensor.
ret = CreateAclTensor(stepRefHostData, stepRefShape, &stepRefDeviceAddr, aclDataType::ACL_INT64, &stepRef);
CHECK_RET(ret == ACL_SUCCESS, return ret);
// Create the result aclTensor.
ret = CreateAclTensor(resultHostData, resultShape, &resultDeviceAddr, aclDataType::ACL_INT32, &result);
if (result == nullptr) {
std::cout << "result is nullptr!" << std::endl;
return 0;
}
CHECK_RET(ret == ACL_SUCCESS, return ret);
// 3. Call the CANN operator library API. Replace with the specific HostApi.
uint64_t workspaceSize = 0;
aclOpExecutor* executor;
// Call the first-phase API of aclnnSilentCheckV2.
ret = aclnnSilentCheckV2GetWorkspaceSize(val, max, avgRef, inputGradRef, stepRef, dstSize, dstStride, dstOffset, cThreshL1, cThreshL2, beta1, npuAsdDetect, result, &workspaceSize, &executor);
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnSilentCheckV2GetWorkspaceSize 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 aclnnSilentCheckV2.
ret = aclnnSilentCheckV2(workspaceAddr, workspaceSize, executor, stream);
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnSilentCheckV2 failed. ERROR: %d\n", ret); return ret);
// 4. (Boilerplate) Synchronously 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 the device memory to the host memory. Modify based on the specific API definition.
PrintOutResult(resultShape, &resultDeviceAddr);
// 6. Release aclTensor and aclScalar. Modify based on the specific API definition.
aclDestroyTensor(val);
aclDestroyTensor(max);
aclDestroyTensor(avgRef);
aclDestroyTensor(inputGradRef);
aclDestroyTensor(stepRef);
aclDestroyIntArray(dstSize);
aclDestroyIntArray(dstStride);
aclDestroyIntArray(dstOffset);
aclDestroyTensor(result);
// 7. Release device resources. Modify based on the specific API definition.
aclrtFree(valDeviceAddr);
aclrtFree(maxDeviceAddr);
aclrtFree(avgRefDeviceAddr);
aclrtFree(inputGradRefDeviceAddr);
aclrtFree(stepRefDeviceAddr);
aclrtFree(resultDeviceAddr);
if (workspaceSize > 0) {
aclrtFree(workspaceAddr);
}
aclrtDestroyStream(stream);
aclrtResetDevice(deviceId);
aclFinalize();
return 0;
}