* Copyright (c) 2026 Huawei Technologies Co., Ltd.
* This program is free software, you can redistribute it and/or modify it under the terms and conditions of
* CANN Open Software License Agreement Version 2.0 (the "License").
* Please refer to the License for details. You may not use this file except in compliance with the License.
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
* See LICENSE in the root of the software repository for the full text of the License.
*/
#include <gtest/gtest.h>
#include "mockcpp/mockcpp.hpp"
#include "executor/indv_bininfo.h"
#include "executor/indv_collector.h"
#include "executor/indv_executor.h"
#include "executor/indv_cache_key_builder.h"
#include "utils/file_faker.h"
#include "utils/indv_soc.h"
#include "utils/thread_var_container.h"
#include "individual_op_api.h"
#include "individual_op_internal.h"
#include "op_cache_internal.h"
#include "depends/op/op_stub.h"
#include "depends/dump/dump_stub.h"
#include "depends/mmpa/mmpa_stub.h"
#include "depends/runtime/runtime_stub.h"
#include "depends/op/aclnn_bninference_d_kernel_stub.h"
#include "opdev/op_executor.h"
#include "utils/indv_lib_wrapper.h"
#include "utils/indv_types.h"
#define private public
#include "executor/indv_args_pool.h"
#include "register/op_binary_resource_manager.h"
#undef private
#ifdef __cplusplus
extern "C" {
#endif
extern aclnnStatus NnopbaseInit();
#ifdef __cplusplus
}
#endif
namespace {
constexpr size_t kExpKeyBufBytes = 10240U;
class NnopbaseCacheKeyUnitTest : public testing::Test {
protected:
void SetUp()
{
setenv("ASCEND_C", "1", 1);
NnopbaseExecutorSetGlobalConfig();
op::internal::opProfilingSwitch.recordOpArgFlag = false;
}
void TearDown()
{
unsetenv("ASCEND_C");
op::internal::opProfilingSwitch.recordOpArgFlag = false;
GlobalMockObject::verify();
}
};
void GetCacheTestExecutor(NnopbaseExecutor*& executor, const char* opType = "bninference_d_kernel",
std::vector<int64_t> shape = {1, 1, 1, 1, 1})
{
static NnopbaseBinCollector* gBinCollector = nullptr;
NnopbaseSetStubFiles(OP_API_COMMON_UT_SRC_DIR);
if (gBinCollector == nullptr) {
gBinCollector = new NnopbaseBinCollector;
ASSERT_NE(gBinCollector, nullptr);
ASSERT_EQ(NnopbaseCollectorInit(gBinCollector), OK);
ASSERT_EQ(NnopbaseCollectorWork(gBinCollector), OK);
}
executor = new NnopbaseExecutor;
ASSERT_NE(executor, nullptr);
char inputDesc[] = {1, 1, 1};
char outputDesc[] = {1};
char attrDesc[] = {};
ASSERT_EQ(
NnopbaseExecutorInit(executor, {inputDesc, sizeof(inputDesc) / sizeof(char), outputDesc,
sizeof(outputDesc) / sizeof(char), attrDesc, sizeof(attrDesc) / sizeof(char)}),
OK);
executor->space = new NnopbaseExecutorSpace();
NnopbaseExecutorSetCollector(executor, gBinCollector);
ASSERT_EQ(NnopbaseExecutorSetRegInfo(executor, opType), OK);
aclTensor* tensor = aclCreateTensor(&shape[0], shape.size(), aclDataType::ACL_FLOAT, nullptr, 0,
aclFormat::ACL_FORMAT_ND, &shape[0], shape.size(), nullptr);
ASSERT_EQ(NnopbaseExecutorUpdateTensorsIndex(&(executor->ownArgs.inputs), 0), OK);
ASSERT_EQ(NnopbaseExecutorAddTensor(executor, tensor, 0, true, false), OK);
ASSERT_EQ(NnopbaseExecutorUpdateTensorsIndex(&(executor->ownArgs.inputs), 1), OK);
ASSERT_EQ(NnopbaseExecutorAddTensor(executor, tensor, 1, true, false), OK);
ASSERT_EQ(NnopbaseExecutorUpdateTensorsIndex(&(executor->ownArgs.inputs), 2), OK);
ASSERT_EQ(NnopbaseExecutorAddTensor(executor, tensor, 2, true, false), OK);
ASSERT_EQ(NnopbaseExecutorUpdateTensorsIndex(&(executor->ownArgs.outputs), 0), OK);
ASSERT_EQ(NnopbaseExecutorAddTensor(executor, tensor, 0, false, false), OK);
aclDestroyTensor(tensor);
}
void GetCacheTestExecutorWithAttr(NnopbaseExecutor*& executor)
{
static NnopbaseBinCollector* gBinCollector = nullptr;
NnopbaseSetStubFiles(OP_API_COMMON_UT_SRC_DIR);
if (gBinCollector == nullptr) {
gBinCollector = new NnopbaseBinCollector;
ASSERT_NE(gBinCollector, nullptr);
ASSERT_EQ(NnopbaseCollectorInit(gBinCollector), OK);
ASSERT_EQ(NnopbaseCollectorWork(gBinCollector), OK);
}
executor = new NnopbaseExecutor;
ASSERT_NE(executor, nullptr);
char inputDesc[] = {1, 1, 1};
char outputDesc[] = {1};
char attrDesc[] = {1};
ASSERT_EQ(
NnopbaseExecutorInit(executor, {inputDesc, sizeof(inputDesc) / sizeof(char), outputDesc,
sizeof(outputDesc) / sizeof(char), attrDesc, sizeof(attrDesc) / sizeof(char)}),
OK);
NnopbaseExecutorSetCollector(executor, gBinCollector);
NnopbaseExecutorSpace space;
executor->space = &space;
ASSERT_EQ(NnopbaseExecutorSetRegInfo(executor, "bninference_d_kernel"), OK);
std::vector<int64_t> shape = {1, 1, 1, 1, 1};
aclTensor* tensor = aclCreateTensor(&shape[0], shape.size(), aclDataType::ACL_FLOAT, nullptr, 0,
aclFormat::ACL_FORMAT_ND, &shape[0], shape.size(), nullptr);
ASSERT_EQ(NnopbaseExecutorUpdateTensorsIndex(&(executor->ownArgs.inputs), 0), OK);
ASSERT_EQ(NnopbaseExecutorAddTensor(executor, tensor, 0, true, false), OK);
ASSERT_EQ(NnopbaseExecutorUpdateTensorsIndex(&(executor->ownArgs.inputs), 1), OK);
ASSERT_EQ(NnopbaseExecutorAddTensor(executor, tensor, 1, true, false), OK);
ASSERT_EQ(NnopbaseExecutorUpdateTensorsIndex(&(executor->ownArgs.inputs), 2), OK);
ASSERT_EQ(NnopbaseExecutorAddTensor(executor, tensor, 2, true, false), OK);
ASSERT_EQ(NnopbaseExecutorUpdateTensorsIndex(&(executor->ownArgs.outputs), 0), OK);
ASSERT_EQ(NnopbaseExecutorAddTensor(executor, tensor, 0, false, false), OK);
static int64_t bias1[1] = {1};
NnopbaseAddAttrWithDtype(executor, bias1, sizeof(int64_t), 0, kNnopbaseInt);
aclDestroyTensor(tensor);
}
void* GetDynamicCacheExecutor(void* executorSpace)
{
const char* opType = "bninference_d_kernel";
char inputDesc[] = {2, 2, 2};
char outputDesc[] = {2};
char attrDesc[] = {};
void* executor = NnopbaseGetExecutor(executorSpace, opType, inputDesc, sizeof(inputDesc) / sizeof(char), outputDesc,
sizeof(outputDesc) / sizeof(char), attrDesc, sizeof(attrDesc) / sizeof(char));
std::vector<int64_t> shape = {1, 1, 1, 1, 1};
aclTensor* tensor = aclCreateTensor(shape.data(), shape.size(), aclDataType::ACL_FLOAT, nullptr, 0,
aclFormat::ACL_FORMAT_ND, shape.data(), shape.size(), nullptr);
std::vector<const aclTensor*> tensorListA;
tensorListA.push_back(tensor);
aclTensorList* aclTensorTestList = aclCreateTensorList(tensorListA.data(), tensorListA.size());
(void)NnopbaseAddDynamicInput(executor, aclTensorTestList, 0);
(void)NnopbaseAddDynamicInput(executor, aclTensorTestList, 1);
(void)NnopbaseAddDynamicInput(executor, aclTensorTestList, 2);
(void)NnopbaseAddDynamicOutput(executor, aclTensorTestList, 0);
aclDestroyTensorList((const aclTensorList*)aclTensorTestList);
return executor;
}
NnopbaseUChar* AppendV1TensorToExp(NnopbaseUChar* key, const NnopbaseTensor& extTensor)
{
if (extTensor.isNull) {
key = NnopbaseAppend1Byte(key, '/');
return key;
}
const auto& rt2Tensor = extTensor.rt2Tensor;
key = NnopbaseAppend1Byte(key, static_cast<NnopbaseUChar>(rt2Tensor.GetDataType()));
key = NnopbaseAppend1Byte(key, static_cast<NnopbaseUChar>(rt2Tensor.GetStorageFormat()));
const auto& shape = rt2Tensor.GetStorageShape();
key = NnopbaseAppend1Byte(key, static_cast<NnopbaseUChar>(shape.GetDimNum()));
for (size_t j = 0; j < shape.GetDimNum(); j++) {
key = static_cast<uint8_t*>(NnopbaseAppend8Byte(key, static_cast<uint64_t>(shape.GetDim(j))));
}
const auto& stride = rt2Tensor.GetStride();
key = NnopbaseAppend1Byte(key, static_cast<NnopbaseUChar>(stride.GetDimNum()));
for (size_t j = 0; j < stride.GetDimNum(); j++) {
key = static_cast<uint8_t*>(NnopbaseAppend8Byte(key, static_cast<uint64_t>(stride.GetStride(j))));
}
key = static_cast<uint8_t*>(NnopbaseAppend8Byte(key, static_cast<uint64_t>(rt2Tensor.GetOffset())));
return key;
}
NnopbaseUChar* BuildV1ExpKey(NnopbaseExecutor* executor, NnopbaseUChar* key)
{
key = static_cast<uint8_t*>(
NnopbaseAppendBinary(key, strlen(executor->opType), executor->opType, strlen(executor->opType)));
auto& inputs = executor->ownArgs.inputs;
for (uint32_t i = 0; i < inputs.num; i++) {
key = AppendV1TensorToExp(key, inputs.extTensors[i]);
}
key = NnopbaseAppend1Byte(key, '/');
auto& outputs = executor->ownArgs.outputs;
for (uint32_t i = 0; i < outputs.num; i++) {
key = AppendV1TensorToExp(key, outputs.extTensors[i]);
}
key = NnopbaseAppend1Byte(key, '/');
return key;
}
NnopbaseUChar* AppendCoreNumExp(NnopbaseUChar* key, const NnopbaseCoreNum& coreNumInfo)
{
key = NnopbaseAppend1Byte(key, '/');
key = static_cast<uint8_t*>(
NnopbaseAppendBinary(key, sizeof(NnopbaseCoreNum), &coreNumInfo, sizeof(NnopbaseCoreNum)));
return key;
}
NnopbaseUChar* AppendTailExp(NnopbaseUChar* key, uint32_t rankId = 0U, bool deterministic = false)
{
key = NnopbaseAppend1Byte(key, '/');
key = static_cast<uint8_t*>(NnopbaseAppendBinary(key, sizeof(uint32_t), &rankId, sizeof(uint32_t)));
key = NnopbaseAppend1Byte(key, '/');
key = NnopbaseAppend1Byte(key, static_cast<NnopbaseUChar>(deterministic));
return key;
}
NnopbaseUChar* AppendIntAttrExp(NnopbaseUChar* key)
{
static int64_t bias1[1] = {1};
return static_cast<uint8_t*>(NnopbaseAppendBinary(key, sizeof(int64_t), &bias1[0], sizeof(int64_t)));
}
}
TEST_F(NnopbaseCacheKeyUnitTest, NnopbaseCacheNoAttrKey)
{
NnopbaseExecutor* executor = nullptr;
GetCacheTestExecutor(executor);
ASSERT_NE(executor, nullptr);
executor->coreNum.aicNum = 24;
executor->coreNum.aivNum = 24;
nnopbase::ArgsPool::GetInstance().MatchArgs(executor);
std::vector<NnopbaseUChar> exp(kExpKeyBufBytes, '\0');
auto key = &exp[0U];
key = BuildV1ExpKey(executor, key);
NnopbaseCoreNum coreNumInfo = {24, 24};
key = AppendCoreNumExp(key, coreNumInfo);
key = AppendTailExp(key);
auto keyLen = key - &exp[0U];
ASSERT_EQ(static_cast<size_t>(keyLen), executor->ownArgs.keyLen);
for (size_t i = 0; i < executor->ownArgs.keyLen; ++i) {
ASSERT_EQ(executor->ownArgs.inputKey[i], exp[i]) << "cache key byte mismatch at offset " << i;
}
NnopbaseExecutorGcSpace((void*)executor->space);
NnopbaseExecutorDeInit(executor);
delete executor;
NnopbaseUnsetEnvAndClearFolder();
}
TEST_F(NnopbaseCacheKeyUnitTest, NnopbaseCacheWithAttrKey)
{
NnopbaseExecutor* executor = nullptr;
GetCacheTestExecutorWithAttr(executor);
ASSERT_NE(executor, nullptr);
executor->space = new NnopbaseExecutorSpace();
executor->coreNum.aicNum = 24;
executor->coreNum.aivNum = 24;
nnopbase::ArgsPool::GetInstance().MatchArgs(executor);
std::vector<NnopbaseUChar> exp(kExpKeyBufBytes, '\0');
auto key = &exp[0U];
key = BuildV1ExpKey(executor, key);
key = AppendIntAttrExp(key);
NnopbaseCoreNum coreNumInfo = {24, 24};
key = AppendCoreNumExp(key, coreNumInfo);
key = AppendTailExp(key);
auto keyLen = key - &exp[0U];
ASSERT_EQ(static_cast<size_t>(keyLen), executor->ownArgs.keyLen);
for (size_t i = 0; i < executor->ownArgs.keyLen; ++i) {
ASSERT_EQ(executor->ownArgs.inputKey[i], exp[i]) << "cache key byte mismatch at offset " << i;
}
NnopbaseExecutorGcSpace((void*)executor->space);
NnopbaseExecutorDeInit(executor);
delete executor;
NnopbaseUnsetEnvAndClearFolder();
}
TEST_F(NnopbaseCacheKeyUnitTest, NnopBaseCacheDynamicIoKey)
{
NnopbaseSetStubFiles(OP_API_COMMON_UT_SRC_DIR);
void* executorSpace = nullptr;
ASSERT_EQ(NnopbaseCreateExecutorSpace(&executorSpace), OK);
void* executor = GetDynamicCacheExecutor(executorSpace);
ASSERT_NE(executor, nullptr);
NnopbaseExecutor* opExecutor = (NnopbaseExecutor*)executor;
opExecutor->coreNum.aicNum = 24;
opExecutor->coreNum.aivNum = 24;
nnopbase::ArgsPool::GetInstance().MatchArgs(opExecutor);
std::vector<NnopbaseUChar> exp(kExpKeyBufBytes, '\0');
auto key = &exp[0U];
key = BuildV1ExpKey(opExecutor, key);
NnopbaseCoreNum coreNumInfo = {24, 24};
key = AppendCoreNumExp(key, coreNumInfo);
key = AppendTailExp(key);
auto keyLen = key - &exp[0U];
ASSERT_EQ(static_cast<size_t>(keyLen), opExecutor->ownArgs.keyLen);
for (size_t i = 0; i < opExecutor->ownArgs.keyLen; ++i) {
ASSERT_EQ(opExecutor->ownArgs.inputKey[i], exp[i]) << "cache key byte mismatch at offset " << i;
}
NnopbaseExecutorGcSpace(executorSpace);
NnopbaseUnsetEnvAndClearFolder();
}
namespace {
constexpr NnopbaseUChar kSeparator = '/';
NnopbaseUChar* AppendV2OpType(NnopbaseUChar* key, const char* opType)
{
return static_cast<NnopbaseUChar*>(NnopbaseAppendBinary(key, strlen(opType), opType, strlen(opType)));
}
NnopbaseUChar* AppendV2TensorShapeInfo(NnopbaseUChar* key, const aclTensor* tensor)
{
const op::Shape& shape = tensor->GetViewShape();
const size_t dimNum = shape.GetDimNum();
const auto& strides = tensor->GetViewStrides();
const size_t strideNum = strides.size();
key = NnopbaseAppend1Byte(key, static_cast<NnopbaseUChar>(tensor->GetDataType()));
key = NnopbaseAppend1Byte(key, static_cast<NnopbaseUChar>(tensor->GetStorageFormat()));
key = NnopbaseAppend1Byte(key, static_cast<NnopbaseUChar>(dimNum));
for (size_t j = 0U; j < dimNum; j++) {
key = NnopbaseAppend8Byte(key, static_cast<uint64_t>(shape.GetDim(j)));
}
key = NnopbaseAppend1Byte(key, static_cast<NnopbaseUChar>(strideNum));
for (size_t j = 0U; j < strideNum; j++) {
key = NnopbaseAppend8Byte(key, static_cast<uint64_t>(strides[j]));
}
key = NnopbaseAppend8Byte(key, static_cast<uint64_t>(tensor->GetViewOffset()));
return key;
}
NnopbaseUChar* AppendV2ValueDependTensor(NnopbaseUChar* key, const void* addr, uint64_t dim, uint64_t dataLen,
ge::DataType dType)
{
key = NnopbaseAppend1Byte(key, static_cast<NnopbaseUChar>(dType));
key = NnopbaseAppend1Byte(key, static_cast<NnopbaseUChar>(ge::FORMAT_ND));
key = NnopbaseAppend1Byte(key, static_cast<NnopbaseUChar>(1U));
key = NnopbaseAppend8Byte(key, dim);
key = static_cast<NnopbaseUChar*>(NnopbaseAppendBinary(key, dataLen, addr, dataLen));
return key;
}
NnopbaseUChar* AppendV2ScalarInfo(NnopbaseUChar* key, ge::DataType dtype)
{
key = NnopbaseAppend1Byte(key, static_cast<NnopbaseUChar>(dtype));
key = NnopbaseAppend1Byte(key, static_cast<NnopbaseUChar>(ge::FORMAT_ND));
key = NnopbaseAppend1Byte(key, static_cast<NnopbaseUChar>(0U));
return key;
}
NnopbaseUChar* AppendV2ScalarListInfo(NnopbaseUChar* key, ge::DataType dtype, uint64_t size)
{
key = NnopbaseAppend1Byte(key, static_cast<NnopbaseUChar>(dtype));
key = NnopbaseAppend1Byte(key, static_cast<NnopbaseUChar>(ge::FORMAT_ND));
key = NnopbaseAppend1Byte(key, static_cast<NnopbaseUChar>(1U));
key = NnopbaseAppend8Byte(key, size);
return key;
}
NnopbaseUChar* AppendV2Placeholder(NnopbaseUChar* key) { return NnopbaseAppend1Byte(key, kSeparator); }
NnopbaseUChar* AppendV2CoreNum(NnopbaseUChar* key, const NnopbaseCoreNum& coreNum)
{
key = NnopbaseAppend1Byte(key, kSeparator);
key = static_cast<NnopbaseUChar*>(
NnopbaseAppendBinary(key, sizeof(NnopbaseCoreNum), &coreNum, sizeof(NnopbaseCoreNum)));
return key;
}
NnopbaseUChar* AppendV2Mc2RankId(NnopbaseUChar* key, uint32_t rankId)
{
key = NnopbaseAppend1Byte(key, kSeparator);
key = static_cast<NnopbaseUChar*>(NnopbaseAppendBinary(key, sizeof(uint32_t), &rankId, sizeof(uint32_t)));
return key;
}
NnopbaseUChar* AppendV2Deterministic(NnopbaseUChar* key, bool deterministic)
{
key = NnopbaseAppend1Byte(key, kSeparator);
key = NnopbaseAppend1Byte(key, static_cast<NnopbaseUChar>(deterministic));
return key;
}
void* PrepareV2Executor(void*& executorSpace, const char* opType, char* inputDesc, size_t inputNum, char* outputDesc,
size_t outputNum, char* attrDesc, size_t attrNum)
{
NnopbaseSetStubFiles(OP_API_COMMON_UT_SRC_DIR);
if (executorSpace == nullptr) {
EXPECT_EQ(NnopbaseCreateExecutorSpace(&executorSpace), OK);
}
void* executor = NnopbaseGetExecutor(executorSpace, opType, inputDesc, inputNum, outputDesc, outputNum, attrDesc,
attrNum);
if (executor != nullptr) {
NnopbaseSetMatchArgsFlag(executor);
}
return executor;
}
void FinishV2MatchArgs(NnopbaseExecutor* executor)
{
executor->coreNum.aicNum = 24;
executor->coreNum.aivNum = 24;
uint64_t workspaceLen = 0U;
(void)NnopbaseMatchArgs(executor, &workspaceLen);
}
}
TEST_F(NnopbaseCacheKeyUnitTest, NnopbaseV2CacheKeyRegularTensor)
{
void* executorSpace = nullptr;
const char* opType = "bninference_d_kernel";
char inputDesc[] = {1, 1, 1};
char outputDesc[] = {1};
char attrDesc[] = {};
void* executor = PrepareV2Executor(executorSpace, opType, inputDesc, sizeof(inputDesc), outputDesc,
sizeof(outputDesc), attrDesc, sizeof(attrDesc));
ASSERT_NE(executor, nullptr);
std::vector<int64_t> shape = {1, 1, 1, 1, 1};
aclTensor* tensor = aclCreateTensor(shape.data(), shape.size(), aclDataType::ACL_FLOAT, nullptr, 0,
aclFormat::ACL_FORMAT_ND, shape.data(), shape.size(), nullptr);
ASSERT_EQ(NnopbaseAddInput(executor, tensor, 0), 0);
ASSERT_EQ(NnopbaseAddInput(executor, tensor, 1), 0);
ASSERT_EQ(NnopbaseAddInput(executor, tensor, 2), 0);
ASSERT_EQ(NnopbaseAddOutput(executor, tensor, 0), 0);
NnopbaseExecutor* opExecutor = static_cast<NnopbaseExecutor*>(executor);
FinishV2MatchArgs(opExecutor);
std::vector<NnopbaseUChar> exp(kExpKeyBufBytes, '\0');
auto key = &exp[0U];
key = AppendV2OpType(key, opType);
key = AppendV2TensorShapeInfo(key, tensor);
key = AppendV2TensorShapeInfo(key, tensor);
key = AppendV2TensorShapeInfo(key, tensor);
key = AppendV2Placeholder(key);
key = AppendV2TensorShapeInfo(key, tensor);
NnopbaseCoreNum coreNumInfo = {24, 24};
key = AppendV2CoreNum(key, coreNumInfo);
key = AppendV2Mc2RankId(key, 0U);
key = AppendV2Deterministic(key, false);
auto keyLen = key - &exp[0U];
ASSERT_EQ(static_cast<size_t>(keyLen), opExecutor->ownArgs.keyLen);
for (size_t i = 0; i < opExecutor->ownArgs.keyLen; ++i) {
ASSERT_EQ(opExecutor->ownArgs.inputKey[i], exp[i]) << "v2 cache key byte mismatch at offset " << i;
}
aclDestroyTensor(tensor);
NnopbaseExecutorGcSpace(executorSpace);
NnopbaseUnsetEnvAndClearFolder();
}
TEST_F(NnopbaseCacheKeyUnitTest, NnopbaseV2CacheKeyNullTensor)
{
void* executorSpace = nullptr;
const char* opType = "bninference_d_kernel";
char inputDesc[] = {1, 0, 1};
char outputDesc[] = {1};
char attrDesc[] = {};
void* executor = PrepareV2Executor(executorSpace, opType, inputDesc, sizeof(inputDesc), outputDesc,
sizeof(outputDesc), attrDesc, sizeof(attrDesc));
ASSERT_NE(executor, nullptr);
std::vector<int64_t> shape = {1, 1, 1, 1, 1};
aclTensor* tensor = aclCreateTensor(shape.data(), shape.size(), aclDataType::ACL_FLOAT, nullptr, 0,
aclFormat::ACL_FORMAT_ND, shape.data(), shape.size(), nullptr);
ASSERT_EQ(NnopbaseAddInput(executor, tensor, 0), 0);
ASSERT_EQ(NnopbaseAddInput(executor, nullptr, 1), 0);
ASSERT_EQ(NnopbaseAddInput(executor, tensor, 2), 0);
ASSERT_EQ(NnopbaseAddOutput(executor, tensor, 0), 0);
NnopbaseExecutor* opExecutor = static_cast<NnopbaseExecutor*>(executor);
FinishV2MatchArgs(opExecutor);
std::vector<NnopbaseUChar> exp(kExpKeyBufBytes, '\0');
auto key = &exp[0U];
key = AppendV2OpType(key, opType);
key = AppendV2TensorShapeInfo(key, tensor);
key = AppendV2Placeholder(key);
key = AppendV2TensorShapeInfo(key, tensor);
key = AppendV2Placeholder(key);
key = AppendV2TensorShapeInfo(key, tensor);
NnopbaseCoreNum coreNumInfo = {24, 24};
key = AppendV2CoreNum(key, coreNumInfo);
key = AppendV2Mc2RankId(key, 0U);
key = AppendV2Deterministic(key, false);
auto keyLen = key - &exp[0U];
ASSERT_EQ(static_cast<size_t>(keyLen), opExecutor->ownArgs.keyLen);
for (size_t i = 0; i < opExecutor->ownArgs.keyLen; ++i) {
ASSERT_EQ(opExecutor->ownArgs.inputKey[i], exp[i]) << "v2 cache key byte mismatch at offset " << i;
}
aclDestroyTensor(tensor);
NnopbaseExecutorGcSpace(executorSpace);
NnopbaseUnsetEnvAndClearFolder();
}
TEST_F(NnopbaseCacheKeyUnitTest, NnopbaseV2CacheKeyIntArray)
{
void* executorSpace = nullptr;
const char* opType = "bninference_d_kernel";
char inputDesc[] = {1, 1, 0};
char outputDesc[] = {1};
char attrDesc[] = {};
void* executor = PrepareV2Executor(executorSpace, opType, inputDesc, sizeof(inputDesc), outputDesc,
sizeof(outputDesc), attrDesc, sizeof(attrDesc));
ASSERT_NE(executor, nullptr);
std::vector<int64_t> shape = {1, 1, 1, 1, 1};
aclTensor* tensor = aclCreateTensor(shape.data(), shape.size(), aclDataType::ACL_FLOAT, nullptr, 0,
aclFormat::ACL_FORMAT_ND, shape.data(), shape.size(), nullptr);
int64_t intValues[] = {3, 4, 5};
auto* intArray = aclCreateIntArray(intValues, sizeof(intValues) / sizeof(intValues[0]));
ASSERT_EQ(NnopbaseAddInput(executor, tensor, 0), 0);
ASSERT_EQ(NnopbaseAddInput(executor, tensor, 1), 0);
ASSERT_EQ(NnopbaseAddIntArrayInput(executor, intArray, 2), OK);
ASSERT_EQ(NnopbaseAddOutput(executor, tensor, 0), 0);
NnopbaseExecutor* opExecutor = static_cast<NnopbaseExecutor*>(executor);
FinishV2MatchArgs(opExecutor);
std::vector<NnopbaseUChar> exp(kExpKeyBufBytes, '\0');
auto key = &exp[0U];
key = AppendV2OpType(key, opType);
key = AppendV2TensorShapeInfo(key, tensor);
key = AppendV2TensorShapeInfo(key, tensor);
key = AppendV2ValueDependTensor(key, intValues, sizeof(intValues) / sizeof(intValues[0]), sizeof(intValues),
ge::DataType::DT_INT64);
key = AppendV2Placeholder(key);
key = AppendV2TensorShapeInfo(key, tensor);
NnopbaseCoreNum coreNumInfo = {24, 24};
key = AppendV2CoreNum(key, coreNumInfo);
key = AppendV2Mc2RankId(key, 0U);
key = AppendV2Deterministic(key, false);
auto keyLen = key - &exp[0U];
ASSERT_EQ(static_cast<size_t>(keyLen), opExecutor->ownArgs.keyLen);
for (size_t i = 0; i < opExecutor->ownArgs.keyLen; ++i) {
ASSERT_EQ(opExecutor->ownArgs.inputKey[i], exp[i]) << "v2 cache key byte mismatch at offset " << i;
}
aclDestroyIntArray(intArray);
aclDestroyTensor(tensor);
NnopbaseExecutorGcSpace(executorSpace);
NnopbaseUnsetEnvAndClearFolder();
}
TEST_F(NnopbaseCacheKeyUnitTest, NnopbaseV2CacheKeyScalar)
{
void* executorSpace = nullptr;
const char* opType = "bninference_d_kernel";
char inputDesc[] = {1, 1, 0};
char outputDesc[] = {1};
char attrDesc[] = {};
void* executor = PrepareV2Executor(executorSpace, opType, inputDesc, sizeof(inputDesc), outputDesc,
sizeof(outputDesc), attrDesc, sizeof(attrDesc));
ASSERT_NE(executor, nullptr);
std::vector<int64_t> shape = {1, 1, 1, 1, 1};
aclTensor* tensor = aclCreateTensor(shape.data(), shape.size(), aclDataType::ACL_FLOAT, nullptr, 0,
aclFormat::ACL_FORMAT_ND, shape.data(), shape.size(), nullptr);
float scalarValue = 5.0f;
auto* scalar = aclCreateScalar(&scalarValue, aclDataType::ACL_FLOAT);
ASSERT_EQ(NnopbaseAddInput(executor, tensor, 0), 0);
ASSERT_EQ(NnopbaseAddInput(executor, tensor, 1), 0);
ASSERT_EQ(NnopbaseAddScalarInput(executor, scalar, 2, -1, ge::DT_UNDEFINED), 0);
ASSERT_EQ(NnopbaseAddOutput(executor, tensor, 0), 0);
NnopbaseExecutor* opExecutor = static_cast<NnopbaseExecutor*>(executor);
FinishV2MatchArgs(opExecutor);
std::vector<NnopbaseUChar> exp(kExpKeyBufBytes, '\0');
auto key = &exp[0U];
key = AppendV2OpType(key, opType);
key = AppendV2TensorShapeInfo(key, tensor);
key = AppendV2TensorShapeInfo(key, tensor);
key = AppendV2ScalarInfo(key, ge::DataType::DT_FLOAT);
key = AppendV2Placeholder(key);
key = AppendV2TensorShapeInfo(key, tensor);
NnopbaseCoreNum coreNumInfo = {24, 24};
key = AppendV2CoreNum(key, coreNumInfo);
key = AppendV2Mc2RankId(key, 0U);
key = AppendV2Deterministic(key, false);
auto keyLen = key - &exp[0U];
ASSERT_EQ(static_cast<size_t>(keyLen), opExecutor->ownArgs.keyLen);
for (size_t i = 0; i < opExecutor->ownArgs.keyLen; ++i) {
ASSERT_EQ(opExecutor->ownArgs.inputKey[i], exp[i]) << "v2 cache key byte mismatch at offset " << i;
}
aclDestroyScalar(scalar);
aclDestroyTensor(tensor);
NnopbaseExecutorGcSpace(executorSpace);
NnopbaseUnsetEnvAndClearFolder();
}
TEST_F(NnopbaseCacheKeyUnitTest, NnopbaseV2CacheKeyScalarList)
{
void* executorSpace = nullptr;
const char* opType = "bninference_d_kernel";
char inputDesc[] = {1, 1, 0};
char outputDesc[] = {1};
char attrDesc[] = {};
void* executor = PrepareV2Executor(executorSpace, opType, inputDesc, sizeof(inputDesc), outputDesc,
sizeof(outputDesc), attrDesc, sizeof(attrDesc));
ASSERT_NE(executor, nullptr);
std::vector<int64_t> shape = {1, 1, 1, 1, 1};
aclTensor* tensor = aclCreateTensor(shape.data(), shape.size(), aclDataType::ACL_FLOAT, nullptr, 0,
aclFormat::ACL_FORMAT_ND, shape.data(), shape.size(), nullptr);
float scalarValue = 5.0f;
auto* scalar = aclCreateScalar(&scalarValue, aclDataType::ACL_FLOAT);
auto* scalarList = aclCreateScalarList(&scalar, 1);
ASSERT_EQ(NnopbaseAddInput(executor, tensor, 0), 0);
ASSERT_EQ(NnopbaseAddInput(executor, tensor, 1), 0);
ASSERT_EQ(NnopbaseAddScalarListInput(executor, scalarList, 2, -1, ge::DT_UNDEFINED), 0);
ASSERT_EQ(NnopbaseAddOutput(executor, tensor, 0), 0);
NnopbaseExecutor* opExecutor = static_cast<NnopbaseExecutor*>(executor);
FinishV2MatchArgs(opExecutor);
std::vector<NnopbaseUChar> exp(kExpKeyBufBytes, '\0');
auto key = &exp[0U];
key = AppendV2OpType(key, opType);
key = AppendV2TensorShapeInfo(key, tensor);
key = AppendV2TensorShapeInfo(key, tensor);
key = AppendV2ScalarListInfo(key, ge::DataType::DT_FLOAT, 1U);
key = AppendV2Placeholder(key);
key = AppendV2TensorShapeInfo(key, tensor);
NnopbaseCoreNum coreNumInfo = {24, 24};
key = AppendV2CoreNum(key, coreNumInfo);
key = AppendV2Mc2RankId(key, 0U);
key = AppendV2Deterministic(key, false);
auto keyLen = key - &exp[0U];
ASSERT_EQ(static_cast<size_t>(keyLen), opExecutor->ownArgs.keyLen);
for (size_t i = 0; i < opExecutor->ownArgs.keyLen; ++i) {
ASSERT_EQ(opExecutor->ownArgs.inputKey[i], exp[i]) << "v2 cache key byte mismatch at offset " << i;
}
aclDestroyScalarList(scalarList);
aclDestroyTensor(tensor);
NnopbaseExecutorGcSpace(executorSpace);
NnopbaseUnsetEnvAndClearFolder();
}
TEST_F(NnopbaseCacheKeyUnitTest, NnopbaseV2CacheKeyDynamicInput)
{
void* executorSpace = nullptr;
const char* opType = "bninference_d_kernel";
char inputDesc[] = {2, 2, 2};
char outputDesc[] = {2};
char attrDesc[] = {};
void* executor = PrepareV2Executor(executorSpace, opType, inputDesc, sizeof(inputDesc), outputDesc,
sizeof(outputDesc), attrDesc, sizeof(attrDesc));
ASSERT_NE(executor, nullptr);
std::vector<int64_t> shape = {1, 1, 1, 1, 1};
aclTensor* tensor = aclCreateTensor(shape.data(), shape.size(), aclDataType::ACL_FLOAT, nullptr, 0,
aclFormat::ACL_FORMAT_ND, shape.data(), shape.size(), nullptr);
std::vector<const aclTensor*> tensorVec;
tensorVec.push_back(tensor);
aclTensorList* tensorList = aclCreateTensorList(tensorVec.data(), tensorVec.size());
ASSERT_EQ(NnopbaseAddDynamicInput(executor, tensorList, 0), 0);
ASSERT_EQ(NnopbaseAddDynamicInput(executor, tensorList, 1), 0);
ASSERT_EQ(NnopbaseAddDynamicInput(executor, tensorList, 2), 0);
ASSERT_EQ(NnopbaseAddDynamicOutput(executor, tensorList, 0), 0);
NnopbaseExecutor* opExecutor = static_cast<NnopbaseExecutor*>(executor);
FinishV2MatchArgs(opExecutor);
std::vector<NnopbaseUChar> exp(kExpKeyBufBytes, '\0');
auto key = &exp[0U];
key = AppendV2OpType(key, opType);
for (uint32_t i = 0; i < 3U; ++i) {
key = AppendV2TensorShapeInfo(key, tensor);
key = NnopbaseAppend1Byte(key, static_cast<NnopbaseUChar>(1U));
}
key = AppendV2Placeholder(key);
key = AppendV2TensorShapeInfo(key, tensor);
key = NnopbaseAppend1Byte(key, static_cast<NnopbaseUChar>(1U));
NnopbaseCoreNum coreNumInfo = {24, 24};
key = AppendV2CoreNum(key, coreNumInfo);
key = AppendV2Mc2RankId(key, 0U);
key = AppendV2Deterministic(key, false);
auto keyLen = key - &exp[0U];
ASSERT_EQ(static_cast<size_t>(keyLen), opExecutor->ownArgs.keyLen);
for (size_t i = 0; i < opExecutor->ownArgs.keyLen; ++i) {
ASSERT_EQ(opExecutor->ownArgs.inputKey[i], exp[i]) << "v2 cache key byte mismatch at offset " << i;
}
aclDestroyTensorList(tensorList);
NnopbaseExecutorGcSpace(executorSpace);
NnopbaseUnsetEnvAndClearFolder();
}