浏览代码

Optimisation - Removed a lot of garbage allocation (#1804)

* Garbage collection optimisations:
- Changed a few IEnumerable instances to IReadOnlyList. This avoids some unnecessary GC allocs that cast the Lists to IEnumerables.
- Moved cdf allocation outside of the loop to avoid unnecessary GC allocation.
- Changed GeneratorImpl to use plain float and int arrays instead of Array during generation. This avoids SetValue performing boxing on the arrays, which eliminates an awful lot of GC allocs.

* Convert InferenceBrain to use IReadOnlyList to avoid garbage creation.
/develop-generalizationTraining-TrainerController
Vincent-Pierre BERGES 6 年前
当前提交
eefe0d6b
共有 6 个文件被更改,包括 20 次插入15 次删除
  1. 2
      UnitySDK/Assets/ML-Agents/Scripts/InferenceBrain/BarracudaModelParamLoader.cs
  2. 20
      UnitySDK/Assets/ML-Agents/Scripts/InferenceBrain/GeneratorImpl.cs
  3. 4
      UnitySDK/Assets/ML-Agents/Scripts/InferenceBrain/ModelParamLoader.cs
  4. 2
      UnitySDK/Assets/ML-Agents/Scripts/InferenceBrain/TFSharpInferenceEngine.cs
  5. 3
      UnitySDK/Assets/ML-Agents/Scripts/InferenceBrain/Utils/Multinomial.cs
  6. 4
      UnitySDK/Assets/ML-Agents/Scripts/LearningBrain.cs

2
UnitySDK/Assets/ML-Agents/Scripts/InferenceBrain/BarracudaModelParamLoader.cs


/// Generates the Tensor inputs that are expected to be present in the Model.
/// </summary>
/// <returns>Tensor IEnumerable with the expected Tensor inputs</returns>
public IEnumerable<Tensor> GetInputTensors()
public IReadOnlyList<Tensor> GetInputTensors()
{
List<Tensor> tensors = new List<Tensor>();

20
UnitySDK/Assets/ML-Agents/Scripts/InferenceBrain/GeneratorImpl.cs


{
tensor.Shape[0] = batchSize;
var vecObsSizeT = tensor.Shape[tensor.Shape.Length - 1];
tensor.Data = new float[batchSize, vecObsSizeT];
var floatArray = new float[batchSize, vecObsSizeT];
tensor.Data = floatArray;
var agentIndex = 0;
foreach (var agent in agentInfo.Keys)
{

tensor.Data.SetValue(vectorObs[j], new int[2] {agentIndex, j});
floatArray[agentIndex, j] = vectorObs[j];
}
agentIndex++;
}

{
tensor.Shape[0] = batchSize;
var memorySize = tensor.Shape[tensor.Shape.Length - 1];
tensor.Data = new float[batchSize, memorySize];
var floatArray = new float[batchSize, memorySize];
tensor.Data = floatArray;
var agentIndex = 0;
foreach (var agent in agentInfo.Keys)
{

{
break;
}
tensor.Data.SetValue(memory[j], new int[2] {agentIndex, j});
floatArray[agentIndex, j] = memory[j];
}
agentIndex++;
}

{
tensor.Shape[0] = batchSize;
var actionSize = tensor.Shape[tensor.Shape.Length - 1];
tensor.Data = new int[batchSize, actionSize];
var intArray = new int[batchSize, actionSize];
tensor.Data = intArray;
var agentIndex = 0;
foreach (var agent in agentInfo.Keys)
{

tensor.Data.SetValue((int) pastAction[j], new int[2] {agentIndex, j});
intArray[agentIndex, j] = (int) pastAction[j];
}
agentIndex++;

{
tensor.Shape[0] = batchSize;
var maskSize = tensor.Shape[tensor.Shape.Length - 1];
tensor.Data = new float[batchSize, maskSize];
var floatArray = new float[batchSize, maskSize];
tensor.Data = floatArray;
var agentIndex = 0;
foreach (var agent in agentInfo.Keys)
{

var isUnmasked = (maskList != null && maskList[j]) ? 0.0f : 1.0f;
tensor.Data.SetValue(isUnmasked, new int[2] {agentIndex, j});
floatArray[agentIndex, j] = isUnmasked;
}
agentIndex++;
}

4
UnitySDK/Assets/ML-Agents/Scripts/InferenceBrain/ModelParamLoader.cs


/// Generates the Tensor inputs that are expected to be present in the Model.
/// </summary>
/// <returns>Tensor IEnumerable with the expected Tensor inputs</returns>
public IEnumerable<Tensor> GetInputTensors()
public IReadOnlyList<Tensor> GetInputTensors()
{
return _engine?.InputFeatures();
}

/// </summary>
/// <returns>Tensor IEnumerable with the expected Tensor outputs</returns>
public IEnumerable<Tensor> GetOutputTensors()
public IReadOnlyList<Tensor> GetOutputTensors()
{
var tensorList = new List<Tensor>();
if (_brainParameters.vectorActionSpaceType == SpaceType.continuous)

2
UnitySDK/Assets/ML-Agents/Scripts/InferenceBrain/TFSharpInferenceEngine.cs


return t;
}
public IEnumerable<Tensor> InputFeatures()
public IReadOnlyList<Tensor> InputFeatures()
{
List<Tensor> inputs = new List<Tensor>();
foreach (var op in m_graph.GetEnumerator())

3
UnitySDK/Assets/ML-Agents/Scripts/InferenceBrain/Utils/Multinomial.cs


throw new ArgumentException("Batch size for input and output data is different!");
}
float[] cdf = new float[input_data.GetLength(1)];
for (int batch = 0; batch < input_data.GetLength(0); ++batch)
{
// Find the class maximum

// Sum the log probabilities and compute CDF
float sumProb = 0.0f;
float[] cdf = new float[input_data.GetLength(1)];
for (int cls = 0; cls < input_data.GetLength(1); ++cls)
{
sumProb += Mathf.Exp(input_data[batch, cls] - maxProb);

4
UnitySDK/Assets/ML-Agents/Scripts/LearningBrain.cs


"(This field is not applicable for training).")]
public InferenceDevice inferenceDevice = InferenceDevice.CPU;
private IEnumerable<Tensor> _inferenceInputs;
private IEnumerable<Tensor> _inferenceOutputs;
private IReadOnlyList<Tensor> _inferenceInputs;
private IReadOnlyList<Tensor> _inferenceOutputs;
[NonSerialized]
private bool _isControlled;

正在加载...
取消
保存