blob: 09b787e1c88c73150fb1387c526c069313ce173a [file] [log] [blame]
lmrb6208c52009-10-07 12:43:24 +00001import os, shutil, logging, re
2from autotest_lib.client.bin import test, utils
3from autotest_lib.client.common_lib import error
4
5class npb(test.test):
6 """
7 This module runs the NAS Parallel Benchmarks on the client machine
8
9 @note: Since we use gfortran to complie these benchmarks, this test might
10 not be able to run on older Operating Systems.
11 @see: http://www.nas.nasa.gov/Resources/Software/npb.html
12 """
13 version = 1
14 def initialize(self, tests=''):
15 # Initialize failure counter
16 self.n_fail = 0
17 # Get the parameters for run_once()
18 self.tests = tests
19 # Ratio is the reason between 1 and the number of CPUs of the system.
20 self.ratio = 1.0 / utils.count_cpus()
21 logging.debug('Ratio (1/n_cpus) found for this system: %s' % self.ratio)
22
23
24 def setup(self, tarball='NPB3.3.tar.gz'):
25 tarball = utils.unmap_url(self.bindir, tarball, self.tmpdir)
26 utils.extract_tarball_to_dir(tarball, self.srcdir)
27 os.chdir(self.srcdir)
28 # Prepare the makefile and benchmarks to generate.
29 utils.system('patch -p1 < ../enable-all-tests.patch')
30 utils.system('cd NPB3.3-OMP && make suite')
31
32
33 def run_once(self):
34 """
35 Run each benchmark twice, with different number of threads.
36
37 A sanity check is made on each benchmark executed:
38 The ratio between the times
39 time_ratio = time_one_thrd / time_full_thrds
40
41 Has to be contained inside an envelope:
42 upper_bound = full_thrds * (1 + (1/n_cpus))
43 lower_bound = full_thrds * (1 - (1/n_cpus))
44
45 Otherwise, we throw an exception (this test might be running under a
46 virtual machine and sanity check failure might mean bugs on smp
47 implementation).
48 """
49 os.chdir(self.srcdir)
50
51 # get the tests to run
52 test_list = self.tests.split()
53
54 if len(test_list) == 0:
55 raise error.TestError('No tests (benchmarks) provided. Exit.')
56
57 for itest in test_list:
58 itest_cmd = os.path.join('NPB3.3-OMP/bin/', itest)
59 try:
60 itest = utils.run(itest_cmd)
61 except:
62 logging.error('NPB benchmark %s has failed. Output: %s',
63 itest_cmd, itest.stdout)
64 self.n_fail += 1
65 logging.debug(itest.stdout)
66
67 # Get the number of threads that the test ran
68 # (which is supposed to be equal to the number of system cores)
69 m = re.search('Total threads\s*=\s*(.*)\n', itest.stdout)
70
71 # Gather benchmark results
72 ts = re.search('Time in seconds\s*=\s*(.*)\n', itest.stdout)
73 mt = re.search('Mop/s total\s*=\s*(.*)\n', itest.stdout)
74 mp = re.search('Mop/s/thread\s*=\s*(.*)\n', itest.stdout)
75
76 time_seconds = float(ts.groups()[0])
77 mops_total = float(mt.groups()[0])
78 mops_per_thread = float(mp.groups()[0])
79
80 logging.info('Test: %s', itest_cmd)
81 logging.info('Time (s): %s', time_seconds)
82 logging.info('Total operations executed (mops/s): %s', mops_total)
83 logging.info('Total operations per thread (mops/s/thread): %s',
84 mops_per_thread)
85
86 self.write_test_keyval({'test': itest_cmd})
87 self.write_test_keyval({'time_seconds': time_seconds})
88 self.write_test_keyval({'mops_total': mops_total})
89 self.write_test_keyval({'mops_per_thread': mops_per_thread})
90
91 # A little extra sanity check comes handy
92 if int(m.groups()[0]) != utils.count_cpus():
93 raise error.TestError("NPB test suite evaluated the number "
94 "of threads incorrectly: System appears "
95 "to have %s cores, but %s threads were "
96 "executed.")
97
98 # We will use this integer with float point vars later.
99 full_thrds = float(m.groups()[0])
100
101 # get duration for full_threads running.
102 m = re.search('Time in seconds\s*=\s*(.*)\n', itest.stdout)
103 time_full_thrds = float(m.groups()[0])
104
105 # repeat the execution with single thread.
106 itest_single_cmd = ''.join(['OMP_NUM_THREADS=1 ', itest_cmd])
107 try:
108 itest_single = utils.run(itest_single_cmd)
109 except:
110 logging.error('NPB benchmark single thread %s has failed. '
111 'Output: %s',
112 itest_single_cmd,
113 itest_single.stdout)
114 self.n_fail += 1
115
116 m = re.search('Time in seconds\s*=\s*(.*)\n', itest_single.stdout)
117 time_one_thrd = float(m.groups()[0])
118
119 # check durations
120 ratio = self.ratio
121 time_ratio = float(time_one_thrd / time_full_thrds)
122 upper_bound = full_thrds * (1 + ratio)
123 lower_bound = full_thrds * (1 - ratio)
124 logging.debug('Time ratio for %s: %s', itest_cmd, time_ratio)
125 logging.debug('Upper bound: %s', upper_bound)
126 logging.debug('Lower bound: %s', lower_bound)
127
128 violates_upper_bound = time_ratio > upper_bound
129 violates_lower_bound = time_ratio < lower_bound
130 if violates_upper_bound or violates_lower_bound:
131 logging.error('NPB benchmark %s failed sanity check '
132 '- time ratio outside bounds' % itest_cmd)
133 self.n_fail += 1
134 else:
135 logging.debug('NPB benchmark %s sanity check PASS' % itest_cmd)
136
137
138 def cleanup(self):
139 """
140 Raise TestError if failures were detected during test execution.
141 """
142 if self.n_fail != 0:
143 raise error.TestError('NPB test failed.')
144 else:
145 logging.info('NPB test passed.')