1##########################################################################
2# Copyright (c) 2009, ETH Zurich.
3# All rights reserved.
4#
5# This file is distributed under the terms in the attached LICENSE file.
6# If you do not find this file, copies can be found by writing to:
7# ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
8##########################################################################
9
10import re
11import debug, tests
12from common import TestCommon, TimeoutError
13from results import RowResults
14
15class SplashMPCommon(TestCommon):
16    def get_module_name(self):
17        raise NotImplementedError
18
19    def get_modules(self, build, machine):
20        modules = super(SplashMPCommon, self).get_modules(build, machine)
21        modules.add_module(self.get_module_name())
22        return modules
23
24    def run(self, build, machine, testdir):
25        modules = self.get_modules(build, machine)
26        ncores = machine.get_ncores()
27        timeouts = 0
28        for i in range(1, ncores + 1):
29            debug.log('running %s iteration %d/%d' % (self.name, i, ncores))
30            yield '[harness: run on %d/%d cores]\n' % (i, ncores)
31            modules.add_module(self.get_module_name(), [str(i)])
32            self.boot(machine, modules)
33            try:
34                for line in self.collect_data(machine):
35                    yield line
36            except TimeoutError:
37                timeouts += 1
38                if timeouts > 1:
39                    # ignore first timeout, will be marked as failed later
40                    continue
41                else:
42                    # something is really wrong
43                    raise
44
45    def process_data(self, testdir, raw_iter):
46        res = RowResults(["cores", "compute_time", "create_time"])
47        createtime = {}
48        computetime = {}
49        seencores = set()
50        maxcores = None
51
52        for line in raw_iter:
53            m = re.match(r"\[harness: run on (\d+)/(\d+) cores\]", line)
54            if m:
55                runcores = int(m.group(1))
56                thismaxcores = int(m.group(2))
57
58                if maxcores is None:
59                    maxcores = thismaxcores
60                elif maxcores != thismaxcores:
61                    res.mark_failed() # inconsistent max #cores in output
62
63                if runcores in seencores or runcores > maxcores:
64                    res.mark_failed() # inconsistent #cores for this run
65                seencores.add(runcores)
66
67                continue
68
69            m = re.match(r"Createtime\s+(\d+)\s+(\d+)", line)
70            if m:
71                createtime[int(m.group(1))] = int(m.group(2))
72                continue
73
74            m = re.match(r"Computetime\s+(\d+)\s+(\d+)", line)
75            if m:
76                computetime[int(m.group(1))] = int(m.group(2))
77
78        allcores = set(createtime.keys()).union(computetime.keys())
79        if allcores == set() or allcores != seencores:
80            res.mark_failed()
81
82        nan = float('nan')
83        allcores = list(allcores)
84        allcores.sort()
85        for c in allcores:
86            a = computetime.get(c, nan)
87            b = createtime.get(c, nan)
88            res.add_row([c, a, b])
89            if a == nan or b == nan:
90                res.mark_failed()
91
92        return res
93
94@tests.add_test
95class BarnesHutTest(SplashMPCommon):
96    '''SPLASH2 Barnes Hut'''
97    name = "BarnesHut"
98    def get_module_name(self):
99        return "splash_barnes"
100
101@tests.add_test
102class RadiosityTest(SplashMPCommon):
103    '''SPLASH2 Radiosity'''
104    name = "Radiosity"
105    def get_module_name(self):
106        return "splash_radiosity"
107
108@tests.add_test
109class BompCgTest(SplashMPCommon):
110    '''NAS OpenMP Compute gradient'''
111    name = "BompCG"
112    def get_module_name(self):
113        return "bomp_benchmark_cg"
114
115@tests.add_test
116class BompFtTest(SplashMPCommon):
117    '''NAS OpenMP FFT'''
118    name = "BompFT"
119    def get_module_name(self):
120        return "bomp_benchmark_ft"
121
122@tests.add_test
123class BompIsTest(SplashMPCommon):
124    '''NAS OpenMP Integer sort'''
125    name = "BompIS"
126    def get_module_name(self):
127        return "bomp_benchmark_is"
128