test: add bounded N64 space-time GPU trajectory harness
This commit is contained in:
@@ -8,6 +8,7 @@ import os
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import time
|
||||
from types import SimpleNamespace
|
||||
import unittest
|
||||
@@ -19,6 +20,7 @@ ROOT = Path(__file__).resolve().parents[3]
|
||||
sys.path.insert(0, str(ROOT/'src'))
|
||||
from CelerisLab.config import LBMConfig
|
||||
import spacetime_gpu as gpu
|
||||
import run_spacetime_gpu_n64 as trajectory
|
||||
ref = gpu.ref
|
||||
RECORDS = []
|
||||
REPORT = None
|
||||
@@ -121,6 +123,76 @@ class Host(unittest.TestCase):
|
||||
self.assertEqual(run.status,'closed'); self.assertEqual(run.allocations,[])
|
||||
second.free.assert_called_once()
|
||||
|
||||
def test_unmeasured_schedule_and_health_failure(self):
|
||||
run=gpu.SpaceTimeGPU.__new__(gpu.SpaceTimeGPU)
|
||||
run.status='ready'; run.step_count=0; run.identity=False; run.mode='spacetime'
|
||||
run.ctx=SimpleNamespace(activate=nullcontext); run.cuda=Mock(); run.stream=Mock()
|
||||
run.plan=self.plan; run.bounds=(3,3,9,8)
|
||||
run.configs=gpu.validate_config(config(12)); run.coarse=list('abcd'); run.fine=list('efg')
|
||||
run.tables=gpu.pack_plan(self.plan); run.device_tables={key:key for key in run.tables}
|
||||
run.active='active'; run.pre='pre'; run.h='h'; run.registers='registers'; run.counts='counts'
|
||||
run.health_counts=np.zeros(6,np.uint64)
|
||||
run.launch=Mock(); run.read=Mock(return_value=np.zeros(6,np.uint32)); run.download=Mock()
|
||||
names=['CoarseStart','Pull','Collide','Interpolate','Collide','Register','Inject','Pull',
|
||||
'Collide','Register','Inject','Pull','ApplyRegisters']
|
||||
for _ in range(2):
|
||||
result=run.step(audit=False)
|
||||
self.assertEqual(result['boundary_budget_status'],'not_measured')
|
||||
self.assertIsNone(result['unexplained'])
|
||||
self.assertEqual([call.args[1] for call in run.launch.call_args_list],names*2)
|
||||
self.assertEqual(run.read.call_count,2); run.download.assert_not_called()
|
||||
self.assertEqual(run.step_count,2); self.assertEqual(run.coarse,list('abcd'))
|
||||
run.read.return_value=np.array([0,0,0,0,1,0],np.uint32)
|
||||
with self.assertRaisesRegex(AssertionError,'health failed'):
|
||||
run.step(audit=False)
|
||||
self.assertEqual(run.status,'failed'); self.assertEqual(run.step_count,2)
|
||||
self.assertEqual(run.health_counts.tolist(),[0,0,0,0,1,0])
|
||||
|
||||
def test_warmup_resets_arrivals_and_counters(self):
|
||||
class Fake:
|
||||
def initialize(self,state):
|
||||
self.state=ref.cpu.State(state.coarse_f.copy(),state.fine_f.copy())
|
||||
self.step_count=0; self.health_counts=np.zeros(6,np.uint64)
|
||||
def download(self):
|
||||
return ref.cpu.State(self.state.coarse_f.copy(),self.state.fine_f.copy(),tick=2*self.step_count)
|
||||
def step(self,*,audit):
|
||||
assert audit is False
|
||||
self.step_count+=1; self.state.coarse_f[:]+=1e-4
|
||||
fake=Fake(); check=Mock(); state=initial(self.plan)
|
||||
actual,warm=trajectory.warm_and_reset(fake,state,check)
|
||||
np.testing.assert_array_equal(actual.coarse_f,state.coarse_f)
|
||||
self.assertEqual(check.call_count,32); self.assertEqual(fake.step_count,0)
|
||||
self.assertTrue(warm['reset_verified']); self.assertEqual(warm['intervals'],32)
|
||||
|
||||
def test_trajectory_screens_differences_and_json(self):
|
||||
rows=[dict(tstar=t,velocity_l2=np.float64(.01),pressure_l2=.03,energy_relative=.01,
|
||||
mass_relative=1e-7,momentum_change=[1e-6,-2e-6],minimum_population=.02,
|
||||
minimum_boundary_pre=.02,minimum_boundary_stored=.02) for t in trajectory.TIMES]
|
||||
cpu=dict(runs=[dict(worst=dict(velocity_l2=.02,pressure_l2=.04,energy_relative=.02)),
|
||||
dict(rows=[dict(tstar=t,velocity_l2=.009,momentum_change=[0.,0.]) for t in trajectory.TIMES])])
|
||||
uniform=dict(rows=[dict(tstar=.12,pressure_l2=.012253173806349701)])
|
||||
result=trajectory.assess(rows,cpu,uniform,[0]*6)
|
||||
self.assertTrue(result['campaign_pass']); self.assertTrue(result['experimental_pass'])
|
||||
self.assertFalse(result['historical_pressure_gate']['passed'])
|
||||
self.assertFalse(result['historical_pressure_gate']['matched_storage'])
|
||||
self.assertAlmostEqual(result['gpu_minus_cpu']['rows'][0]['fields']['velocity_l2']['signed'],.001)
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
path=Path(directory)/'receipt.json'
|
||||
ref.write_receipt(path,dict(completed=True,**result))
|
||||
self.assertTrue(json.loads(path.read_text())['completed'])
|
||||
rows[0]['velocity_l2']=.06
|
||||
failed=trajectory.assess(rows,cpu,uniform,[0,1,0,0,0,0])
|
||||
ref.write_receipt(path,dict(completed=True,**failed))
|
||||
saved=json.loads(path.read_text())
|
||||
self.assertFalse(saved['campaign_pass']); self.assertFalse(saved['experimental_pass'])
|
||||
for invalid in (float('nan'),-.01):
|
||||
rows[0]['velocity_l2']=.01; rows[-1]['velocity_l2']=invalid
|
||||
failed=trajectory.assess(rows,cpu,uniform,[0]*6)
|
||||
self.assertFalse(failed['campaign_pass']); self.assertFalse(failed['experimental_pass'])
|
||||
path.write_text('changed reference')
|
||||
with self.assertRaisesRegex(ValueError,'pinned reference'):
|
||||
trajectory.load_references(path,path)
|
||||
|
||||
|
||||
class Device(unittest.TestCase):
|
||||
@classmethod
|
||||
@@ -214,6 +286,25 @@ class Device(unittest.TestCase):
|
||||
device_bytes=run.device_bytes,table_sha256=gpu.table_hash(run.tables),
|
||||
build_metadata=run.build_metadata,device=self.context.name))
|
||||
|
||||
def test_unmeasured_path_and_warm_reset(self):
|
||||
with gpu.SpaceTimeGPU(config(12),(3,3,9,8),context=self.context) as run:
|
||||
state=initial(run.plan)
|
||||
run.initialize(state)
|
||||
for _ in range(2):
|
||||
run.step()
|
||||
expected=run.download()
|
||||
run.initialize(state)
|
||||
for _ in range(2):
|
||||
result=run.step(audit=False)
|
||||
self.assertEqual(result['boundary_budget_status'],'not_measured')
|
||||
actual=run.download()
|
||||
for a,b in zip((actual.coarse_f,actual.fine_f),(expected.coarse_f,expected.fine_f)):
|
||||
np.testing.assert_array_equal(a,b)
|
||||
reset,warm=trajectory.warm_and_reset(run,state,lambda:None)
|
||||
for a,b in zip((reset.coarse_f,reset.fine_f),(state.coarse_f,state.fine_f)):
|
||||
np.testing.assert_array_equal(a,b.astype(np.float32))
|
||||
record(dict(case='unmeasured_bitwise_and_reset',warmup=warm,health_counts=run.health_counts.tolist()))
|
||||
|
||||
|
||||
def main():
|
||||
global REPORT,OUTPUT,GPU_ADMITTED
|
||||
|
||||
Reference in New Issue
Block a user