Migrate Atmospherics to TensorPrimitives (#44139)

This commit is contained in:
ArtisticRoomba
2026-06-02 12:52:50 -07:00
committed by GitHub
parent 96a977a8a2
commit faa9ead594
9 changed files with 43 additions and 44 deletions
+1 -1
View File
@@ -32,7 +32,7 @@ public class DeltaPressureBenchmark
/// <summary>
/// Number of entities (windows, really) to spawn with a <see cref="DeltaPressureComponent"/>.
/// </summary>
[Params(1, 10, 100, 1000, 5000, 10000, 50000, 100000)]
[Params(100, 1000, 5000, 10000)]
public int EntityCount;
/// <summary>
@@ -1,3 +1,4 @@
using System.Numerics.Tensors;
using System.Runtime.CompilerServices;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Reactions;
@@ -26,15 +27,15 @@ public sealed partial class AtmosphereSystem
public override bool IsMixtureFuel(GasMixture mixture, float epsilon = Atmospherics.Epsilon)
{
var tmp = new float[Atmospherics.AdjustedNumberOfGases];
NumericsHelpers.Multiply(mixture.Moles, GasFuelMask, tmp);
return NumericsHelpers.HorizontalAdd(tmp) > epsilon;
TensorPrimitives.Multiply(mixture.Moles, GasFuelMask, tmp);
return TensorPrimitives.Sum(tmp) > epsilon;
}
public override bool IsMixtureOxidizer(GasMixture mixture, float epsilon = Atmospherics.Epsilon)
{
var tmp = new float[Atmospherics.AdjustedNumberOfGases];
NumericsHelpers.Multiply(mixture.Moles, GasOxidizerMask, tmp);
return NumericsHelpers.HorizontalAdd(tmp) > epsilon;
TensorPrimitives.Multiply(mixture.Moles, GasOxidizerMask, tmp);
return TensorPrimitives.Sum(tmp) > epsilon;
}
public override float GetMass(GasMixture mix)
@@ -45,17 +46,17 @@ public sealed partial class AtmosphereSystem
public override float GetMass(float[] moles)
{
var tmp = new float[moles.Length];
NumericsHelpers.Multiply(moles, GasMolarMasses, tmp);
TensorPrimitives.Multiply(moles, GasMolarMasses, tmp);
// Conversion of grams to kilograms.
return NumericsHelpers.HorizontalAdd(tmp) * Atmospherics.gToKg;
return TensorPrimitives.Sum(tmp) * Atmospherics.gToKg;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
protected override float GetHeatCapacityCalculation(float[] moles, bool space)
{
// Little hack to make space gas mixtures have heat capacity, therefore allowing them to cool down rooms.
if (space && MathHelper.CloseTo(NumericsHelpers.HorizontalAdd(moles), 0f))
if (space && MathHelper.CloseTo(TensorPrimitives.Sum(moles), 0f))
{
return Atmospherics.SpaceHeatCapacity;
}
@@ -65,9 +66,9 @@ public sealed partial class AtmosphereSystem
// though this isnt the hottest code path so it should be fine
// the gc can eat a little as a treat
var tmp = new float[moles.Length];
NumericsHelpers.Multiply(moles, GasMolarHeatCapacities, tmp);
TensorPrimitives.Multiply(moles, GasMolarHeatCapacities, tmp);
// Adjust heat capacity by speedup, because this is primarily what
// determines how quickly gases heat up/cool.
return MathF.Max(NumericsHelpers.HorizontalAdd(tmp), Atmospherics.MinimumHeatCapacity);
return MathF.Max(TensorPrimitives.Sum(tmp), Atmospherics.MinimumHeatCapacity);
}
}
@@ -1,5 +1,6 @@
using System.Buffers;
using System.Diagnostics;
using System.Numerics.Tensors;
using Content.Server.NodeContainer.NodeGroups;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Components;
@@ -366,10 +367,9 @@ public partial class AtmosphereSystem
mixtMoles[i] = mixture.TotalMoles;
}
// TODO NumericsHelpers need a method that substitutes NaNs with zeros. AVX-512 has one iirc but for 256/128 we need to do some masking bs
NumericsHelpers.Multiply(mixtMoles, Atmospherics.R);
NumericsHelpers.Multiply(mixtMoles, mixtTemp);
NumericsHelpers.Divide(mixtMoles, mixtVol, pressures);
TensorPrimitives.Multiply(mixtMoles, Atmospherics.R, mixtMoles);
TensorPrimitives.Multiply(mixtMoles, mixtTemp, mixtMoles);
TensorPrimitives.Divide(mixtMoles, mixtVol, pressures);
}
finally
{
@@ -1,5 +1,6 @@
using System.Buffers;
using System.Collections.Concurrent;
using System.Numerics.Tensors;
using Content.Server.Atmos.Components;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Components;
@@ -162,9 +163,9 @@ public sealed partial class AtmosphereSystem
}
// Time to get crankin
NumericsHelpers.Max(groupA, groupB, groupMax);
NumericsHelpers.Sub(groupA, groupB);
NumericsHelpers.Abs(groupA);
TensorPrimitives.Max(groupA, groupB, groupMax);
TensorPrimitives.Subtract(groupA, groupB, groupA);
TensorPrimitives.Abs(groupA, groupA);
// Now go through each entity and determine their max pressure & delta pressure.
// Queue for damage if necessary.
@@ -1,4 +1,5 @@
using System.Linq;
using System.Numerics.Tensors;
using System.Runtime.CompilerServices;
using Content.Server.Atmos.Reactions;
using Content.Shared.Atmos;
@@ -36,40 +37,40 @@ namespace Content.Server.Atmos.EntitySystems
public override float GetMass(float[] moles)
{
Span<float> tmp = stackalloc float[moles.Length];
NumericsHelpers.Multiply(moles, GasMolarMasses, tmp);
TensorPrimitives.Multiply(moles, GasMolarMasses, tmp);
// Conversion of grams to kilograms.
return NumericsHelpers.HorizontalAdd(tmp) * Atmospherics.gToKg;
return TensorPrimitives.Sum(tmp) * Atmospherics.gToKg;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
protected override float GetHeatCapacityCalculation(float[] moles, bool space)
{
// Little hack to make space gas mixtures have heat capacity, therefore allowing them to cool down rooms.
if (space && MathHelper.CloseTo(NumericsHelpers.HorizontalAdd(moles), 0f))
if (space && MathHelper.CloseTo(TensorPrimitives.Sum(moles), 0f))
{
return Atmospherics.SpaceHeatCapacity;
}
Span<float> tmp = stackalloc float[moles.Length];
NumericsHelpers.Multiply(moles, GasMolarHeatCapacities, tmp);
TensorPrimitives.Multiply(moles, GasMolarHeatCapacities, tmp);
// Adjust heat capacity by speedup, because this is primarily what
// determines how quickly gases heat up/cool.
return MathF.Max(NumericsHelpers.HorizontalAdd(tmp), Atmospherics.MinimumHeatCapacity);
return MathF.Max(TensorPrimitives.Sum(tmp), Atmospherics.MinimumHeatCapacity);
}
public override bool IsMixtureFuel(GasMixture mixture, float epsilon = Atmospherics.Epsilon)
{
Span<float> tmp = stackalloc float[Atmospherics.AdjustedNumberOfGases];
NumericsHelpers.Multiply(mixture.Moles, GasFuelMask, tmp);
return NumericsHelpers.HorizontalAdd(tmp) > epsilon;
TensorPrimitives.Multiply(mixture.Moles, GasFuelMask, tmp);
return TensorPrimitives.Sum(tmp) > epsilon;
}
public override bool IsMixtureOxidizer(GasMixture mixture, float epsilon = Atmospherics.Epsilon)
{
Span<float> tmp = stackalloc float[Atmospherics.AdjustedNumberOfGases];
NumericsHelpers.Multiply(mixture.Moles, GasOxidizerMask, tmp);
return NumericsHelpers.HorizontalAdd(tmp) > epsilon;
TensorPrimitives.Multiply(mixture.Moles, GasOxidizerMask, tmp);
return TensorPrimitives.Sum(tmp) > epsilon;
}
/// <summary>
@@ -131,8 +132,8 @@ namespace Content.Server.Atmos.EntitySystems
}
// transfer moles
NumericsHelpers.Multiply(source.Moles, fraction, buffer);
NumericsHelpers.Add(receiver.Moles, buffer);
TensorPrimitives.Multiply(source.Moles, fraction, buffer);
TensorPrimitives.Add(receiver.Moles, buffer, receiver.Moles);
}
}
@@ -325,13 +326,8 @@ namespace Content.Server.Atmos.EntitySystems
[PublicAPI]
public static void AddMolsToMixture(GasMixture mixture, ReadOnlySpan<float> molsToAdd)
{
// Span length should be as long as the length of the gas array.
// Technically this is a redundant check because NumericsHelpers will do the same thing,
// but eh.
ArgumentOutOfRangeException.ThrowIfNotEqual(mixture.Moles.Length, molsToAdd.Length, nameof(mixture.Moles.Length));
NumericsHelpers.Add(mixture.Moles, molsToAdd);
NumericsHelpers.Max(mixture.Moles, 0f);
TensorPrimitives.Add(mixture.Moles, molsToAdd, mixture.Moles);
TensorPrimitives.Max(mixture.Moles, 0f, mixture.Moles);
}
public enum GasCompareResult
@@ -1,3 +1,4 @@
using System.Numerics.Tensors;
using System.Runtime.CompilerServices;
using Content.Shared.Atmos.Prototypes;
using Content.Shared.Atmos.Reactions;
@@ -110,7 +111,7 @@ public abstract partial class SharedAtmosphereSystem
[PublicAPI]
public void GetFlammableMoles(GasMixture mixture, float[] buffer)
{
NumericsHelpers.Multiply(mixture.Moles, GasOxidiserFuelMask, buffer);
TensorPrimitives.Multiply(mixture.Moles, GasOxidiserFuelMask, buffer);
}
/// <summary>
@@ -213,7 +214,7 @@ public abstract partial class SharedAtmosphereSystem
}
}
NumericsHelpers.Add(receiver.Moles, giver.Moles);
TensorPrimitives.Add(receiver.Moles, giver.Moles, receiver.Moles);
}
/// <summary>
+5 -4
View File
@@ -1,6 +1,7 @@
using System.Collections;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Numerics.Tensors;
using System.Runtime.CompilerServices;
using Content.Shared.Atmos.EntitySystems;
using Content.Shared.Atmos.Reactions;
@@ -42,7 +43,7 @@ namespace Content.Shared.Atmos
public float TotalMoles
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => NumericsHelpers.HorizontalAdd(Moles);
get => TensorPrimitives.Sum(Moles);
}
[ViewVariables]
@@ -177,9 +178,9 @@ namespace Content.Shared.Atmos
var removed = new GasMixture(Volume) { Temperature = Temperature };
Moles.CopyTo(removed.Moles.AsSpan());
NumericsHelpers.Multiply(removed.Moles, ratio);
TensorPrimitives.Multiply(removed.Moles, ratio, removed.Moles);
if (!Immutable)
NumericsHelpers.Sub(Moles, removed.Moles);
TensorPrimitives.Subtract(Moles, removed.Moles, Moles);
for (var i = 0; i < Moles.Length; i++)
{
@@ -223,7 +224,7 @@ namespace Content.Shared.Atmos
public void Multiply(float multiplier)
{
if (Immutable) return;
NumericsHelpers.Multiply(Moles, multiplier);
TensorPrimitives.Multiply(Moles, multiplier, Moles);
}
void ISerializationHooks.AfterDeserialization()
+1
View File
@@ -6,6 +6,7 @@
<Import Project="../MSBuild/Content.props" />
<ItemGroup>
<PackageReference Include="JetBrains.Annotations" PrivateAssets="All" />
<PackageReference Include="System.Numerics.Tensors" />
<PackageReference Include="YamlDotNet" />
</ItemGroup>
@@ -21,10 +21,8 @@ public sealed class AddMolsToMixtureTest
var mixture = new GasMixture();
var wrongLength = new float[Atmospherics.AdjustedNumberOfGases + num];
var ex = Assert.Throws<ArgumentOutOfRangeException>(() =>
Assert.Throws<ArgumentException>(() =>
AtmosphereSystem.AddMolsToMixture(mixture, wrongLength));
Assert.That(ex!.ParamName, Is.EqualTo("Length"));
}
/// <summary>