Skip to content

Commit 4b5675d

Browse files
committed
test(math): implement diagnostic benchmark for deterministic math parity
- Add RUN_MATH_BENCHMARK_REPLAY400_FLAG to SimulationMathCrc.h - Implement 10000-iteration dual-path benchmark in SimulationMathCrc.cpp - Inject benchmark trigger into GameLogic::update at replay frame 400 - Benchmark measures CRT vs WWMath precision and performance
1 parent a344ef2 commit 4b5675d

3 files changed

Lines changed: 97 additions & 4 deletions

File tree

Core/GameEngine/Include/Common/Diagnostic/SimulationMathCrc.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,12 @@
1818

1919
#pragma once
2020

21+
// Flags for diagnostic math benchmarks
22+
// #define RUN_MATH_BENCHMARK_REPLAY400_FLAG
23+
2124
class SimulationMathCrc
2225
{
2326
public:
2427
static UnsignedInt calculate();
28+
static void runBenchmark(int iterations = 10000);
2529
};

Core/GameEngine/Source/Common/Diagnostic/SimulationMathCrc.cpp

Lines changed: 76 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,10 @@
2525
#include "GameLogic/FPUControl.h"
2626

2727
#include <math.h>
28+
#include <stdio.h>
29+
#include <time.h>
2830

29-
static void appendSimulationMathCrc(XferCRC &xfer)
31+
static void appendSimulationMathCrc_Deterministic(XferCRC &xfer)
3032
{
3133
Matrix3D matrix;
3234
Matrix3D factorsMatrix;
@@ -37,8 +39,8 @@ static void appendSimulationMathCrc(XferCRC &xfer)
3739
0.9f, 1.0f, 2.1f, 1.2f);
3840

3941
factorsMatrix.Set(
40-
WWMath::Sin(0.7f) * log10f(2.3f),
41-
WWMath::Cos(1.1f) * powf(1.1f, 2.0f),
42+
WWMath::Sin(0.7f) * WWMath::Log10fOrigin(2.3f),
43+
WWMath::Cos(1.1f) * WWMath::PowfOrigin(1.1f, 2.0f),
4244
WWMath::TanfOrigin(0.3f),
4345
WWMath::ASinfOrigin(0.967302263f),
4446
WWMath::ACosfOrigin(0.967302263f),
@@ -56,18 +58,88 @@ static void appendSimulationMathCrc(XferCRC &xfer)
5658
xfer.xferMatrix3D(&matrix);
5759
}
5860

61+
static void appendSimulationMathCrc_Native(XferCRC &xfer)
62+
{
63+
Matrix3D matrix;
64+
Matrix3D factorsMatrix;
65+
66+
matrix.Set(
67+
4.1f, 1.2f, 0.3f, 0.4f,
68+
0.5f, 3.6f, 0.7f, 0.8f,
69+
0.9f, 1.0f, 2.1f, 1.2f);
70+
71+
factorsMatrix.Set(
72+
(float)(::sin(0.7) * ::log10(2.3)),
73+
(float)(::cos(1.1) * ::pow(1.1, 2.0)),
74+
(float)::tan(0.3),
75+
(float)::asin(0.967302263),
76+
(float)::acos(0.967302263),
77+
(float)(::atan(0.967302263) * ::pow(1.1, 2.0)),
78+
(float)::atan2(0.4, 1.3),
79+
(float)::sinh(0.2),
80+
(float)(::cosh(0.4) * ::tanh(0.5)),
81+
(float)::sqrt(55788.84375),
82+
(float)(::exp(0.1) * ::log10(2.3)),
83+
(float)::log(1.4));
84+
85+
Matrix3D::Multiply(matrix, factorsMatrix, &matrix);
86+
matrix.Get_Inverse(matrix);
87+
88+
xfer.xferMatrix3D(&matrix);
89+
}
90+
5991
UnsignedInt SimulationMathCrc::calculate()
6092
{
6193
XferCRC xfer;
6294
xfer.open("SimulationMathCrc");
6395

6496
setFPMode();
6597

66-
appendSimulationMathCrc(xfer);
98+
appendSimulationMathCrc_Deterministic(xfer);
6799

68100
_fpreset();
69101

70102
xfer.close();
71103

72104
return xfer.getCRC();
73105
}
106+
107+
void SimulationMathCrc::runBenchmark(int iterations)
108+
{
109+
clock_t startDet = clock();
110+
UnsignedInt crcDet = 0;
111+
112+
setFPMode();
113+
for (int i = 0; i < iterations; ++i)
114+
{
115+
XferCRC xfer;
116+
xfer.open("SimMathDet");
117+
appendSimulationMathCrc_Deterministic(xfer);
118+
xfer.close();
119+
if (i == 0) crcDet = xfer.getCRC();
120+
}
121+
_fpreset();
122+
clock_t endDet = clock();
123+
double timeDetMs = (double)(endDet - startDet) / CLOCKS_PER_SEC * 1000.0;
124+
125+
clock_t startNat = clock();
126+
UnsignedInt crcNat = 0;
127+
128+
setFPMode();
129+
for (int i = 0; i < iterations; ++i)
130+
{
131+
XferCRC xfer;
132+
xfer.open("SimMathNat");
133+
appendSimulationMathCrc_Native(xfer);
134+
xfer.close();
135+
if (i == 0) crcNat = xfer.getCRC();
136+
}
137+
_fpreset();
138+
clock_t endNat = clock();
139+
double timeNatMs = (double)(endNat - startNat) / CLOCKS_PER_SEC * 1000.0;
140+
141+
printf("\n================ MATH BENCHMARK (%d iters) ================\n", iterations);
142+
printf("Deterministic (WWMath): CRC = %08X, Time = %.2f ms\n", crcDet, timeDetMs);
143+
printf("Native (system math): CRC = %08X, Time = %.2f ms\n", crcNat, timeNatMs);
144+
printf("===========================================================\n\n");
145+
}

GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "Common/AudioHandleSpecialValues.h"
3434
#include "Common/BuildAssistant.h"
3535
#include "Common/CRCDebug.h"
36+
#include "Common/Diagnostic/SimulationMathCrc.h"
3637
#include "Common/FramePacer.h"
3738
#include "Common/GameAudio.h"
3839
#include "Common/GameEngine.h"
@@ -3738,6 +3739,22 @@ void GameLogic::update()
37383739
TheTerrainLogic->UPDATE();
37393740
}
37403741

3742+
#ifdef RUN_MATH_BENCHMARK_REPLAY400_FLAG
3743+
static int s_replayStartFrame = -1;
3744+
static bool s_benchmarkRun = false;
3745+
3746+
if (!s_benchmarkRun && TheRecorder && TheRecorder->isPlaybackMode())
3747+
{
3748+
if (s_replayStartFrame == -1) {
3749+
s_replayStartFrame = m_frame;
3750+
}
3751+
else if (m_frame == s_replayStartFrame + 400) {
3752+
SimulationMathCrc::runBenchmark(10000);
3753+
s_benchmarkRun = true;
3754+
}
3755+
}
3756+
#endif
3757+
37413758
// force CRC calculation, so we can keep a cache of the last N CRCs. We do this right where the recorder
37423759
// would be getting the CRC anyway, so replays can get the CRCs from the exact instant in time as the original.
37433760
Bool isMPGameOrReplay = (TheRecorder && TheRecorder->isMultiplayer() && getGameMode() != GAME_SHELL && getGameMode() != GAME_NONE);

0 commit comments

Comments
 (0)