Skip to content

Commit 1863bbd

Browse files
author
Victor Holanda
committed
Promote DGEMM check to multinode
1 parent 11f9963 commit 1863bbd

File tree

2 files changed

+103
-43
lines changed

2 files changed

+103
-43
lines changed

cscs-checks/libraries/math/dgemm.py

Lines changed: 81 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,48 +2,98 @@
22
import reframe.utility.sanity as sn
33

44

5+
@rfm.required_version('>=2.14')
6+
@rfm.simple_test
57
class DGEMMTest(rfm.RegressionTest):
68
def __init__(self):
79
super().__init__()
810
self.descr = 'DGEMM performance test'
911
self.sourcepath = 'dgemm.c'
10-
self.executable_opts = ['5000', '5000', '5000']
11-
self.sanity_patterns = sn.assert_found(
12-
r'Time for \d+ DGEMM operations', self.stdout)
13-
self.maintainers = ['AJ']
14-
self.tags = {'production'}
1512

13+
self.sanity_patterns = self.eval_sanity()
14+
# the perf patterns are automaticaly generated inside sanity
15+
self.perf_patterns = {}
1616

17-
@rfm.required_version('>=2.14')
18-
@rfm.simple_test
19-
class DGEMMTestMonch(DGEMMTest):
20-
def __init__(self):
21-
super().__init__()
22-
self.tags = {'monch_acceptance'}
23-
self.valid_systems = ['monch:compute']
24-
self.valid_prog_environs = ['PrgEnv-gnu']
25-
self.num_tasks = 1
17+
self.valid_systems = ['daint:gpu', 'daint:mc', 'dom:gpu', 'dom:mc',
18+
'monch:compute']
19+
self.valid_prog_environs = ['PrgEnv-cray', 'PrgEnv-gnu', 'PrgEnv-intel']
20+
21+
# FIXME: set the num_tasks to zero.
22+
self.num_tasks = 2
2623
self.num_tasks_per_node = 1
2724
self.num_tasks_per_core = 1
28-
self.num_cpus_per_task = 20
29-
self.num_tasks_per_socket = 10
25+
self.num_tasks_per_socket = 1
3026
self.use_multithreading = False
27+
28+
self.build_system = 'SingleSource'
29+
self.build_system.cflags = ['-O3']
30+
31+
self.my_reference = {
32+
'daint:gpu': (430, -0.1, None),
33+
'daint:mc': (430, -0.1, None),
34+
'monch:compute': (350, -0.1, None),
35+
}
36+
37+
self.maintainers = ['AJ', 'VH', 'VK']
38+
self.tags = {'production'}
39+
40+
41+
def setup(self, partition, environ, **job_opts):
42+
if partition.fullname in ['daint:gpu', 'dom:gpu']:
43+
self.num_cpus_per_task = 12
44+
self.executable_opts = ['6000', '6000', '6000']
45+
46+
elif partition.fullname in ['daint:mc', 'dom:mc']:
47+
self.num_cpus_per_task = 36
48+
self.executable_opts = ['6000', '6000', '6000']
49+
50+
elif partition.fullname in ['monch:compute']:
51+
self.num_cpus_per_task = 20
52+
self.executable_opts = ['5000', '5000', '5000']
53+
self.build_system.cflags += ['-I$EBROOTOPENBLAS/include']
54+
self.build_system.ldflags = ['-L$EBROOTOPENBLAS/lib', '-lopenblas',
55+
'-lpthread', '-lgfortran']
56+
3157
self.variables = {
3258
'OMP_NUM_THREADS': str(self.num_cpus_per_task),
3359
'MV2_ENABLE_AFFINITY': '0'
3460
}
35-
self.build_system = 'SingleSource'
36-
self.build_system.cflags = ['-O3', '-I$EBROOTOPENBLAS/include']
37-
self.build_system.ldflags = ['-L$EBROOTOPENBLAS/lib', '-lopenblas',
38-
'-lpthread', '-lgfortran']
39-
self.perf_patterns = {
40-
'perf': sn.max(
41-
sn.extractall(r'Run\s\d\s+:\s+(?P<gflops>\S+)\s\S+',
42-
self.stdout, "gflops", float)
43-
)
44-
}
45-
self.reference = {
46-
'monch:compute': {
47-
'perf': (350, -0.1, None)
48-
}
49-
}
61+
62+
if environ.name.startswith('PrgEnv-cray'):
63+
self.build_system.cflags += ['-hnoomp']
64+
65+
super().setup(partition, environ, **job_opts)
66+
67+
68+
@sn.sanity_function
69+
def eval_sanity(self):
70+
failures = []
71+
72+
all_tested_nodes = sn.evaluate(sn.findall(
73+
r'(?P<name>.*):\s+Time for \d+ DGEMM operations',
74+
self.stdout
75+
))
76+
number_of_tested_nodes = len(all_tested_nodes)
77+
78+
if number_of_tested_nodes != self.num_tasks:
79+
failures.append('Requested %s nodes, but found %s nodes)' %
80+
(self.num_tasks, number_of_tested_nodes))
81+
#FIXME: list detected nodes in error message
82+
sn.assert_false(failures, msg=', '.join(failures))
83+
84+
update_reference = False
85+
if self.my_reference[self.current_partition.fullname]:
86+
update_reference = True
87+
88+
for node in all_tested_nodes:
89+
nodename = node.group('name')
90+
91+
if update_reference:
92+
partition_name = self.current_partition.fullname
93+
ref_name = '%s:%s' % (partition_name, nodename)
94+
self.reference[ref_name] = self.my_reference[partition_name]
95+
self.perf_patterns[nodename] = sn.extractsingle(
96+
'%s:\\s+Flops based on.*:\\s+(?P<gflops>.*)\\sGFlops\\/sec'
97+
% nodename, self.stdout, "gflops", float)
98+
99+
return sn.assert_false(failures, msg=', '.join(failures))

cscs-checks/libraries/math/src/dgemm.c

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include <stdio.h>
22
#include <stdlib.h>
33
#include <sys/time.h>
4+
#include <unistd.h>
45

56
extern void dgemm_(char*, char*, int*, int*, int*, double*, double*,
67
int*, double*, int*, double*, double*, int*);
@@ -22,7 +23,15 @@ int main(int argc, char* argv[])
2223
char tb='N';
2324

2425
struct timeval start_time, end_time, duration[LOOP_COUNT];
25-
26+
27+
28+
#ifndef HOST_NAME_MAX
29+
#define HOST_NAME_MAX sysconf (_SC_HOST_NAME_MAX)
30+
#endif
31+
32+
char hostname[HOST_NAME_MAX];
33+
gethostname(hostname, sizeof(hostname));
34+
2635
if (argc >= 2) m = atoi(argv[1]);
2736
if (argc >= 3) n = atoi(argv[2]);
2837
if (argc >= 4) k = atoi(argv[3]);
@@ -34,10 +43,10 @@ int main(int argc, char* argv[])
3443
double* B = (double*)malloc(sizeof(double)*k*n);
3544
double* C = (double*)malloc(sizeof(double)*m*n);
3645

37-
printf("Size of Matrix A(mxk)\t\t:\t%d x %d\n", m, k);
38-
printf("Size of Matrix B(kxn)\t\t:\t%d x %d\n", k, n);
39-
printf("Size of Matrix C(mxn)\t\t:\t%d x %d\n", m, n);
40-
printf("LOOP COUNT\t\t\t:\t%d \n", LOOP_COUNT);
46+
printf("%s: Size of Matrix A(mxk)\t\t:\t%d x %d\n", hostname, m, k);
47+
printf("%s: Size of Matrix B(kxn)\t\t:\t%d x %d\n", hostname, k, n);
48+
printf("%s: Size of Matrix C(mxn)\t\t:\t%d x %d\n", hostname, m, n);
49+
printf("%s: LOOP COUNT\t\t\t:\t%d \n", hostname, LOOP_COUNT);
4150
printf("\n");
4251

4352
for (i=0; i<m*k ; ++i) A[i] = i%3+1;
@@ -48,7 +57,7 @@ int main(int argc, char* argv[])
4857

4958
/* CALL DGEMM ONCE TO INITIALIZE THREAD/BUFFER */
5059
dgemm_(&ta, &tb, &m, &n, &k, &alpha, A, &m, B, &k, &beta, C, &m);
51-
60+
5261
/* LOOP OVER DGEMM IN ORDER TO SMOOTHEN THE RESULTS */
5362
for (i=0; i<LOOP_COUNT; ++i)
5463
{
@@ -57,20 +66,21 @@ int main(int argc, char* argv[])
5766
gettimeofday(&end_time,NULL);
5867
timersub(&end_time, &start_time, &duration[i]);
5968
}
60-
69+
70+
time_avg = 0.0;
6171
for (i=0; i<LOOP_COUNT; ++i)
6272
{
63-
time[i] = (duration[i].tv_sec * 1.e3 +
73+
time[i] = (duration[i].tv_sec * 1.e3 +
6474
duration[i].tv_usec * 1.e-3) * 1.e-3;
6575
perf[i] = gflop / time[i];
6676
time_avg += time[i];
67-
printf("Run %d \t\t\t\t:\t%.5f GFlops/sec\n", i, perf[i]);
77+
printf("%s: Run %d \t\t\t\t:\t%.5f GFlops/sec\n", hostname, i, perf[i]);
6878
}
6979

7080
printf("\n");
71-
printf("Flops based on given dimensions\t:\t%.5f GFlops/sec\n", gflop);
72-
printf("Avg. time / DGEMM operation\t:\t%f secs \n", time_avg/LOOP_COUNT);
73-
printf("Time for %d DGEMM operations\t:\t%f secs \n", LOOP_COUNT, time_avg);
81+
printf("%s: Flops based on given dimensions\t:\t%.5f GFlops/sec\n", hostname, gflop);
82+
printf("%s: Avg. time / DGEMM operation\t:\t%f secs \n", hostname, time_avg/LOOP_COUNT);
83+
printf("%s: Time for %d DGEMM operations\t:\t%f secs \n", hostname, LOOP_COUNT, time_avg);
7484
printf("\n");
7585

7686
return 0;

0 commit comments

Comments
 (0)