Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CONTRIBUTORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@
|-----------------|------------------|-------------|------------|
| andrewcoughtrie | Andrew Coughtrie | Met Office | 2026-03-05 |
| mo-marqh | mark Hedley | Met Office | 2026-03-10 |
| oakleybrunt | Oakley Brunt | Met Office | 2026-03-09 |
| oakleybrunt | Oakley Brunt | Met Office | 2026-03-09 |
| EdHone | Ed Hone | Met Office | 2026-03-20 |
8 changes: 4 additions & 4 deletions post-processing/tests/data/vernier-output-test
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ Profiling on 1 thread(s).
(Size; Size/sec; Size/call; MinSize; MaxSize)
(self) (sec) (sec) (sec) ms/call ms/call

1 44.130 2.583 2.583 5.854 1 2583.167 5853.527 __test_app__
2 34.563 4.606 2.023 2.077 2 1011.582 1038.697 some_process
1 44.130 2.583 2.583 5.854 1 2583.167 5853.527 __test_app__@0
2 34.563 4.606 2.023 2.077 2 1011.582 1038.697 some_process@0

Task 2 of 2 : MPI rank ID 1
Profiling on 1 thread(s).
Expand All @@ -16,5 +16,5 @@ Profiling on 1 thread(s).
(Size; Size/sec; Size/call; MinSize; MaxSize)
(self) (sec) (sec) (sec) ms/call ms/call

1 43.991 3.009 3.009 3.069 2 1504.362 1534.740 some_process
2 37.835 5.596 2.588 6.839 1 2587.638 6839.336 __test_app__
1 43.991 3.009 3.009 3.069 2 1504.362 1534.740 some_process@0
2 37.835 5.596 2.588 6.839 1 2587.638 6839.336 __test_app__@0
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@

Task 1 of 2 : MPI rank ID 0
Profiling on 4 thread(s).

# % Time Cumul Self Total # of calls Self Total Routine@
(Size; Size/sec; Size/call; MinSize; MaxSize)
(self) (sec) (sec) (sec) ms/call ms/call

1 40.000 2.000 2.000 3.000 2 1000.075 1500.115 MAIN_SUB@0
2 40.000 4.000 2.000 5.000 1 2000.140 5000.373 FULL@0
3 20.000 5.000 1.000 1.000 1 1000.073 1000.073 MAIN_SUB2@3
4 20.000 6.000 1.000 2.000 1 1000.072 2000.152 MAIN_SUB@3
5 20.000 7.001 1.000 1.000 1 1000.072 1000.072 MAIN_SUB2@0
6 20.000 8.001 1.000 1.000 1 1000.071 1000.071 MAIN_SUB2@2
7 20.000 9.001 1.000 1.000 1 1000.069 1000.069 MAIN_SUB2@1
8 20.000 10.001 1.000 2.000 1 1000.068 2000.151 MAIN_SUB@2
9 20.000 11.001 1.000 2.000 1 1000.067 2000.150 MAIN_SUB@1
10 0.000 11.001 0.000 0.000 2 0.008 0.008 __vernier__@2
11 0.000 11.001 0.000 0.000 4 0.004 0.004 __vernier__@0
12 0.000 11.001 0.000 0.000 2 0.008 0.008 __vernier__@1
13 0.000 11.001 0.000 0.000 2 0.007 0.007 __vernier__@3
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@

Task 2 of 2 : MPI rank ID 1
Profiling on 4 thread(s).

# % Time Cumul Self Total # of calls Self Total Routine@
(Size; Size/sec; Size/call; MinSize; MaxSize)
(self) (sec) (sec) (sec) ms/call ms/call

1 40.031 2.004 2.004 5.006 1 2003.948 5005.940 FULL@0
2 39.956 4.004 2.000 3.002 2 1000.084 1500.991 MAIN_SUB@0
3 20.056 5.008 1.004 1.004 1 1003.995 1003.995 MAIN_SUB2@1
4 20.017 6.010 1.002 1.002 1 1002.034 1002.034 MAIN_SUB2@3
5 20.012 7.012 1.002 1.002 1 1001.809 1001.809 MAIN_SUB2@0
6 19.979 8.012 1.000 1.000 1 1000.149 1000.149 MAIN_SUB2@2
7 19.978 9.012 1.000 2.004 1 1000.063 2004.060 MAIN_SUB@1
8 19.978 10.012 1.000 2.002 1 1000.063 2002.101 MAIN_SUB@3
9 19.977 11.012 1.000 2.000 1 1000.038 2000.191 MAIN_SUB@2
10 0.002 11.012 0.000 0.000 2 0.052 0.052 __vernier__@2
11 0.002 11.012 0.000 0.000 2 0.052 0.052 __vernier__@1
12 0.002 11.013 0.000 0.000 2 0.052 0.052 __vernier__@3
13 0.001 11.013 0.000 0.000 4 0.007 0.007 __vernier__@0
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ Profiling on 1 thread(s).
(Size; Size/sec; Size/call; MinSize; MaxSize)
(self) (sec) (sec) (sec) ms/call ms/call

1 44.130 2.583 2.583 5.854 1 2583.167 5853.527 __test_app__
2 34.563 4.606 2.023 2.077 2 1011.582 1038.697 some_process
1 44.130 2.583 2.583 5.854 1 2583.167 5853.527 __test_app__@0
2 34.563 4.606 2.023 2.077 2 1011.582 1038.697 some_process@0
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ Profiling on 1 thread(s).
(Size; Size/sec; Size/call; MinSize; MaxSize)
(self) (sec) (sec) (sec) ms/call ms/call

1 43.991 3.009 3.009 3.069 2 1504.362 1534.740 some_process
2 37.835 5.596 2.588 6.839 1 2587.638 6839.336 __test_app__
1 43.991 3.009 3.009 3.069 2 1504.362 1534.740 some_process@0
2 37.835 5.596 2.588 6.839 1 2587.638 6839.336 __test_app__@0
6 changes: 3 additions & 3 deletions post-processing/tests/test_cli_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ def setUp(self):
self.test_data_dir = Path(__file__).parent / 'data'
# pylint: disable=line-too-long
self.test_data_kgo = (
'| Routine | Total time (s) | Self (s) | Cumul time (s) | No. calls | % time | Time per call (s) |\n' +
'| __test_app__ | 6.3465 | 2.5855 | 4.0895 | 1 | 40.9825 | 6.3465 |\n' +
'| some_process | 2.573 | 2.516 | 3.8075 | 2 | 39.277 | 1.2865 |\n'
'| Routine | Total time (s) | Self (s) | Cumul time (s) | Max no. calls | % time | Time per call (s) |\n' +
'| __test_app__ | 6.3465 | 2.5855 | 4.0895 | 1 | 40.9825 | 6.3465 |\n' +
'| some_process | 2.573 | 2.516 | 3.8075 | 2 | 39.277 | 1.2865 |\n'
)
return super().setUp()

Expand Down
108 changes: 90 additions & 18 deletions post-processing/tests/test_vernier_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,71 @@ def test_add_empty_calliper(self):
self.assertEqual(self.test_data.data["test_calliper"].self_time, [])
self.assertEqual(self.test_data.data["test_calliper"].total_time, [])
self.assertEqual(self.test_data.data["test_calliper"].n_calls, [])
self.assertEqual(self.test_data.data["test_calliper"].rank, [])
self.assertEqual(self.test_data.data["test_calliper"].thread, [])

def test_get(self):
"""
Tests that the get method of VernierData returns the expected data.
"""
self.test_data.add_calliper("test_calliper")
self.test_data.data["test_calliper"].time_percent = [10.0, 20.0]
self.test_data.data["test_calliper"].cumul_time = [30.0, 40.0]
self.test_data.data["test_calliper"].self_time = [5.0, 15.0]
self.test_data.data["test_calliper"].total_time = [25.0, 35.0]
self.test_data.data["test_calliper"].n_calls = [2, 2]
self.test_data.data["test_calliper"].rank = [0, 1]
self.test_data.data["test_calliper"].thread = [0, 0]
calliper_data = self.test_data.get("test_calliper")
self.assertEqual(calliper_data.time_percent, [10.0, 20.0])
self.assertEqual(calliper_data.cumul_time, [30.0, 40.0])
self.assertEqual(calliper_data.self_time, [5.0, 15.0])
self.assertEqual(calliper_data.total_time, [25.0, 35.0])
self.assertEqual(calliper_data.n_calls, [2, 2])
self.assertEqual(calliper_data.rank, [0, 1])
self.assertEqual(calliper_data.thread, [0, 0])

def test_get_rank(self):
"""
Tests getter for data from a single rank
"""
self.test_data.add_calliper("test_calliper")
self.test_data.data["test_calliper"].time_percent = [10.0, 20.0]
self.test_data.data["test_calliper"].cumul_time = [30.0, 40.0]
self.test_data.data["test_calliper"].self_time = [5.0, 15.0]
self.test_data.data["test_calliper"].total_time = [25.0, 35.0]
self.test_data.data["test_calliper"].n_calls = [2, 2]
self.test_data.data["test_calliper"].rank = [0, 1]
self.test_data.data["test_calliper"].thread = [0, 0]
calliper_data = self.test_data.get("test_calliper", rank=1)
self.assertEqual(calliper_data.time_percent, [20.0])
self.assertEqual(calliper_data.cumul_time, [40.0])
self.assertEqual(calliper_data.self_time, [15.0])
self.assertEqual(calliper_data.total_time, [35.0])
self.assertEqual(calliper_data.n_calls, [2])
self.assertEqual(calliper_data.rank, [1])
self.assertEqual(calliper_data.thread, [0])

def test_get_thread(self):
"""
Tests getter for data from a single thread
"""
self.test_data.add_calliper("test_calliper")
self.test_data.data["test_calliper"].time_percent = [10.0, 20.0]
self.test_data.data["test_calliper"].cumul_time = [30.0, 40.0]
self.test_data.data["test_calliper"].self_time = [5.0, 15.0]
self.test_data.data["test_calliper"].total_time = [25.0, 35.0]
self.test_data.data["test_calliper"].n_calls = [2, 2]
self.test_data.data["test_calliper"].rank = [0, 0]
self.test_data.data["test_calliper"].thread = [0, 1]
calliper_data = self.test_data.get("test_calliper", thread=1)
self.assertEqual(calliper_data.time_percent, [20.0])
self.assertEqual(calliper_data.cumul_time, [40.0])
self.assertEqual(calliper_data.self_time, [15.0])
self.assertEqual(calliper_data.total_time, [35.0])
self.assertEqual(calliper_data.n_calls, [2])
self.assertEqual(calliper_data.rank, [0])
self.assertEqual(calliper_data.thread, [1])

def test_filter_calliper(self):
"""
Expand Down Expand Up @@ -91,14 +156,16 @@ def test_write_txt_output_file(self):
self.test_data.data["test_calliper"].self_time = [5.0, 15.0]
self.test_data.data["test_calliper"].total_time = [25.0, 35.0]
self.test_data.data["test_calliper"].n_calls = [2]
self.test_data.data["test_calliper"].rank = [0, 1]
self.test_data.data["test_calliper"].thread = [0, 0]

# pylint: disable=unspecified-encoding
with tempfile.NamedTemporaryFile(delete=False) as tmp_file:
self.test_data.write_txt_output(Path(tmp_file.name))
contents = Path(tmp_file.name).read_text().splitlines()
# pylint: disable=line-too-long
self.assertEqual("| Routine | Total time (s) | Self (s) | Cumul time (s) | No. calls | % time | Time per call (s) |", contents[0])
self.assertEqual("| test_calliper | 30.0 | 10.0 | 35.0 | 2 | 15.0 | 15.0 |", contents[1])
self.assertEqual("| Routine | Total time (s) | Self (s) | Cumul time (s) | Max no. calls | % time | Time per call (s) |", contents[0])
self.assertEqual("| test_calliper | 30.0 | 10.0 | 35.0 | 2 | 15.0 | 15.0 |", contents[1])

def test_write_txt_output_terminal(self):
"""
Expand All @@ -111,15 +178,17 @@ def test_write_txt_output_terminal(self):
self.test_data.data["test_calliper"].self_time = [3.0, 4.0]
self.test_data.data["test_calliper"].total_time = [15.0, 55.0]
self.test_data.data["test_calliper"].n_calls = [2]
self.test_data.data["test_calliper"].rank = [0, 1]
self.test_data.data["test_calliper"].thread = [0, 0]

write_output = StringIO()
sys.stdout = write_output
self.test_data.write_txt_output()
sys.stdout = sys.__stdout__

# pylint: disable=line-too-long
self.assertEqual("| Routine | Total time (s) | Self (s) | Cumul time (s) | No. calls | % time | Time per call (s) |", write_output.getvalue().splitlines()[0])
self.assertEqual("| test_calliper | 35.0 | 3.5 | 11.0 | 2 | 45.0 | 17.5 |", write_output.getvalue().splitlines()[1])
self.assertEqual("| Routine | Total time (s) | Self (s) | Cumul time (s) | Max no. calls | % time | Time per call (s) |", write_output.getvalue().splitlines()[0])
self.assertEqual("| test_calliper | 35.0 | 3.5 | 11.0 | 2 | 45.0 | 17.5 |", write_output.getvalue().splitlines()[1])

def test_aggregate(self):
"""
Expand All @@ -133,6 +202,8 @@ def test_aggregate(self):
data1.data["calliper_a"].self_time = [5.0, 15.0]
data1.data["calliper_a"].total_time = [25.0, 35.0]
data1.data["calliper_a"].n_calls = [2, 2]
data1.data["calliper_a"].rank = [0, 1]
data1.data["calliper_a"].thread = [0, 0]

data2 = VernierData()
data2.add_calliper("calliper_a")
Expand All @@ -141,6 +212,8 @@ def test_aggregate(self):
data2.data["calliper_a"].self_time = [6.0, 16.0]
data2.data["calliper_a"].total_time = [28.0, 38.0]
data2.data["calliper_a"].n_calls = [3, 3]
data2.data["calliper_a"].rank = [0, 1]
data2.data["calliper_a"].thread = [0, 0]

aggregated = VernierData()
aggregated.aggregate([data1, data2])
Expand Down Expand Up @@ -174,6 +247,8 @@ def test_aggregate_inconsistent(self):
data1.data["calliper_a"].self_time = [5.0, 15.0]
data1.data["calliper_a"].total_time = [25.0, 35.0]
data1.data["calliper_a"].n_calls = [2, 2]
data1.data["calliper_a"].rank = [0, 1]
data1.data["calliper_a"].thread = [0, 0]

data2 = VernierData()
data2.add_calliper("calliper_b")
Expand All @@ -182,6 +257,8 @@ def test_aggregate_inconsistent(self):
data2.data["calliper_b"].self_time = [6.0, 16.0]
data2.data["calliper_b"].total_time = [28.0, 38.0]
data2.data["calliper_b"].n_calls = [3, 3]
data2.data["calliper_b"].rank = [0, 1]
data2.data["calliper_b"].thread = [0, 0]

with self.assertRaises(ValueError):
aggregated = VernierData()
Expand All @@ -203,19 +280,6 @@ def test_aggregate_inconsistent_ok(self):
self.assertIn("calliper_a", aggregated.data)
self.assertIn("calliper_b", aggregated.data)

def test_get(self):
"""
Test that the get method of the VernierData class works as expected.
"""
data1 = VernierData()
data1.add_calliper("calliper_a")
data1.data["calliper_a"].time_percent = [10.0, 20.0]
data1.data["calliper_a"].cumul_time = [30.0, 40.0]
data1.data["calliper_a"].self_time = [5.0, 15.0]
data1.data["calliper_a"].total_time = [25.0, 35.0]
data1.data["calliper_a"].n_calls = [2, 2]
self.assertEqual(len(data1.get("calliper_a")), 2)


class TestVernierCollation(unittest.TestCase):
"""
Expand All @@ -233,6 +297,8 @@ def _add_data(self):
data1.data["calliper_a"].self_time = [5.0, 15.0]
data1.data["calliper_a"].total_time = [25.0, 35.0]
data1.data["calliper_a"].n_calls = [2, 2]
data1.data["calliper_a"].rank = [0, 1]
data1.data["calliper_a"].thread = [0, 0]

data2 = VernierData()
data2.add_calliper("calliper_a")
Expand All @@ -241,6 +307,8 @@ def _add_data(self):
data2.data["calliper_a"].self_time = [6.0, 16.0]
data2.data["calliper_a"].total_time = [28.0, 38.0]
data2.data["calliper_a"].n_calls = [3, 3]
data2.data["calliper_a"].rank = [0, 1]
data2.data["calliper_a"].thread = [0, 0]

self.collation.add_data('test1', data1)
self.collation.add_data('test2', data2)
Expand All @@ -262,7 +330,7 @@ def test_remove_data(self):
self.collation.remove_data('test1')
self.assertEqual(len(self.collation), 1)

def test_get(self):
def test_get__collation(self):
"""
Test that the get method of VernierCollation returns the expected
VernierData instance.
Expand All @@ -284,13 +352,17 @@ def test_internal_consistency(self):
data_inc.data["calliper_a"].self_time = [5.0, 15.0]
data_inc.data["calliper_a"].total_time = [25.0, 35.0]
data_inc.data["calliper_a"].n_calls = [2, 2]
data_inc.data["calliper_a"].rank = [0, 1]
data_inc.data["calliper_a"].thread = [0, 0]

data_inc.add_calliper("calliper_b")
data_inc.data["calliper_b"].time_percent = [15.0, 25.0]
data_inc.data["calliper_b"].cumul_time = [35.0, 45.0]
data_inc.data["calliper_b"].self_time = [6.0, 16.0]
data_inc.data["calliper_b"].total_time = [28.0, 38.0]
data_inc.data["calliper_b"].n_calls = [3, 3]
data_inc.data["calliper_b"].rank = [0, 1]
data_inc.data["calliper_b"].thread = [0, 0]

with self.assertRaises(ValueError) as test_exception:
self.collation.add_data('test3', data_inc)
Expand Down
Loading
Loading