NNE_RUNTIME_BASIC_CHECK_ALIASING happens in LearningAgents

I have the memory disabled (as I understand, the problem is there cause FLinearLayer::Evaluate gets the same pointer for input and output), and this check is happening from time to time. The inference is called during PPOTrainer training in the tick function in the sync mode. The engine version is 5.6. The call stack is:

UE::NNE::RuntimeBasic::Private::OperatorLinear(float *restrict,const float *__restrict,const float *__restrict,const float *__restrict,const unsigned int,const unsigned int,const unsigned int,const unsigned int,const unsigned int) NNERuntimeBasicCpuModel.cpp:436
UE::NNE::RuntimeBasic::Private::FLinearLayer::Evaluate(UE::NNE::RuntimeBasic::Private::ILayerInstance *, float *, const float *, const unsigned int, const unsigned int, const unsigned int, const unsigned int, const unsigned int) NNERuntimeBasicCpuModel.cpp:2012
UE::NNE::RuntimeBasic::Private::FMemoryCellLayer::Evaluate(UE::NNE::RuntimeBasic::Private::ILayerInstance *, float *, const float *, const unsigned int, const unsigned int, const unsigned int, const unsigned int, const unsigned int) NNERuntimeBasicCpuModel.cpp:2602
UE::NNE::RuntimeBasic::Private::FSequenceLayer::Evaluate(UE::NNE::RuntimeBasic::Private::ILayerInstance *, float *, const float *, const unsigned int, const unsigned int, const unsigned int, const unsigned int, const unsigned int) NNERuntimeBasicCpuModel.cpp:1754
UE::NNE::RuntimeBasic::FModelInstanceCPU::RunSync(TArrayView<…>, TArrayView<…>) NNERuntimeBasicCpuModel.cpp:4868
UE::Learning::FNeuralNetworkInference::Evaluate(TMultiArrayView<…>, TMultiArrayView<…>) LearningNeuralNetwork.cpp:345
UE::Learning::FNeuralNetworkFunction::Evaluate(TMultiArrayView<…>, TMultiArrayView<…>, FIndexSet) LearningNeuralNetwork.cpp:392
UE::Learning::FNeuralNetworkPolicy::Evaluate(TMultiArrayView<…>, TMultiArrayView<…>, TMultiArrayView<…>, TMultiArrayView<…>, FIndexSet) LearningPolicy.cpp:52
ULearningAgentsPolicy::EvaluatePolicy() LearningAgentsPolicy.cpp:649
ULearningAgentsPolicy::RunInference(const float) LearningAgentsPolicy.cpp:755
ULearningAgentsPPOTrainer::RunTraining(const FLearningAgentsPPOTrainingSettings &, const FLearningAgentsTrainingGameSettings &, const bool, const bool) LearningAgentsPPOTrainer.cpp:713

Update: We’re also running the simulation in fixed-timestep mode at 60 FPS (which we set in the training settings). I suspect the issue may occur when the simulation is sped up too much, potentially exposing a race condition in some internal memory allocation logic. However, I’m not certain about the exact cause, so any insight would be appreciated.

The issue was a false positive aliasing check: because MemorySize was 0, the input pointer was computed as OutputBuffer + OutputSize, which pointed to the end of the previous output block, but the actual input range was empty. Sometimes the output scratch buffer was allocated starting at the same address, so InputBuffer == OutputBuffer, and the pointer-only alias check failed. However, there was no real overlap, and no input was read because the input had zero length.

In 5.6, it can be fixed in PIE by turning off checks in UBT or enabling the memory for the policy. In the later engine versions, the assert has been improved by Epic so it shouldn’t produce false positive results.