parallelize fmv/fcvt unit tests
authorJacob Lifshay <programmerjake@gmail.com>
Fri, 19 May 2023 01:01:08 +0000 (18:01 -0700)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Fri, 2 Jun 2023 18:51:18 +0000 (19:51 +0100)
src/openpower/decoder/isa/test_caller_fmv_fcvt.py

index cf5730b788a8758ffa2c53e75c475bb46372dba1..8bb903469a3ec685aacfeb0d223f9e2f592f4153 100644 (file)
@@ -2,6 +2,7 @@
 """
 
 import unittest
+from functools import lru_cache
 
 from openpower.test.fmv_fcvt.fmv_fcvt import (FMvFCvtCases,
                                               SVP64FMvFCvtCases)
@@ -10,14 +11,52 @@ from openpower.test.runner import TestRunnerBase
 # writing the test_caller invocation this way makes it work with pytest
 
 
-class TestFMvFCvtCases(TestRunnerBase):
+@lru_cache()
+def make_cases():
+    # cache globally, so we only have to create test_data once per process
+    return FMvFCvtCases().test_data
+
+
+class TestFMvFCvtBase(TestRunnerBase):
+    __test__ = False
+
+    # split up test cases into SPLIT_COUNT tests, so we get some parallelism
+    SPLIT_COUNT = 16
+    SPLIT_INDEX = -1
+
     def __init__(self, test):
-        assert test == 'test'
-        super().__init__(FMvFCvtCases().test_data, fp=True)
+        assert test == 'test', f"test={test!r}"
+        cases = make_cases()
+        assert self.SPLIT_INDEX != -1, "must be overridden"
+        # split cases evenly over tests
+        start = (len(cases) * self.SPLIT_INDEX) // self.SPLIT_COUNT
+        end = (len(cases) * (self.SPLIT_INDEX + 1)) // self.SPLIT_COUNT
+        # if we have less cases than tests, move them all to the beginning,
+        # making finding failures faster
+        if len(cases) < self.SPLIT_COUNT:
+            start = 0
+            end = 0
+            if self.SPLIT_INDEX < len(cases):
+                start = self.SPLIT_INDEX
+                end = start + 1
+        # can't do raise SkipTest if `start == end`, it makes unittest break
+        super().__init__(cases[start:end], fp=True)
+
+    @classmethod
+    def make_split_classes(cls):
+        for i in range(cls.SPLIT_COUNT):
+            exec(f"""
+class TestFMvFCvt{i}(TestFMvFCvtBase):
+    __test__ = True
+    SPLIT_INDEX = {i}
 
     def test(self):
         # dummy function to make unittest try to test this class
         pass
+            """, globals())
+
+
+TestFMvFCvtBase.make_split_classes()
 
 
 class TestSVP64FMvFCvtCases(TestRunnerBase):