Merge lp:~manjo/checkbox/stress-test into lp:checkbox

Proposed by Manoj Iyer
Status: Rejected
Rejected by: Zygmunt Krynicki
Proposed branch: lp:~manjo/checkbox/stress-test
Merge into: lp:checkbox
Diff against target: 267 lines (+263/-0)
1 file modified
checkbox-old/scripts/cpustress.c (+263/-0)
To merge this branch: bzr merge lp:~manjo/checkbox/stress-test
Reviewer Review Type Date Requested Status
Zygmunt Krynicki (community) Disapprove
Daniel Manrique (community) Needs Information
Jeff Lane  Pending
Brendan Donegan Pending
Review via email: mp+196957@code.launchpad.net

Description of the change

Test case to stress CPU integer and floating point paths. It also exercises CPU path that deals with data and text cache misses. On ARMHF this test was able to cause the CPU core temperature to rise to 50c and a power draw of 13.70Watts.

To post a comment you must log in.
Revision history for this message
Daniel Manrique (roadmr) wrote :

Hi Manoj,

This may be more specialized than the stress test we're currently using (apt-get install stress), however I'd like to confirm with you that the existing stress program is unsuitable for this purpose. This is because when possible, we prefer to rely on existing packages since then the maintenance burden on checkbox is reduced.

Have you tried the stress program I mentioned? if so, what problems do you see with it? is it something unsolvable, or something that we could solve by tweaking e.g. command-line parameters?

review: Needs Information
Revision history for this message
Manoj Iyer (manjo) wrote :

Daniel,

I know of the stress program, infact I was one of the contributors to it. stress is designed to put stress on the system , ie it is a load generator. It generates load on the CPU by executing sqrt on a random number. What my test program does is it exercises the floating point and integer parts of the CPU and the path on the processor that deals with data and test cache misses. This is done using NXN vector multiplication and depending on input params you can cause the cpu to really work hard and draw close to max wattage.

Revision history for this message
Manoj Iyer (manjo) wrote :

> Hi Manoj,
>
> This may be more specialized than the stress test we're currently using (apt-
> get install stress), however I'd like to confirm with you that the existing
> stress program is unsuitable for this purpose. This is because when possible,
> we prefer to rely on existing packages since then the maintenance burden on
> checkbox is reduced.
>
> Have you tried the stress program I mentioned? if so, what problems do you see
> with it? is it something unsolvable, or something that we could solve by
> tweaking e.g. command-line parameters?

I can try and submit this test program to debian to see if they will accept it. I built a deb package for it in https://launchpad.net/~calxeda-armhf/+archive/calxeda-ppa if you want to review.

Revision history for this message
Daniel Manrique (roadmr) wrote :

Hi Manoj, thanks for replying.

I think your test could be conceivably useful (and used!) outside of checkbox, thus, in the end proposing it to debian (or ubuntu if you like) as a package, and having checkbox depend/suggest it would be best; that way it's not tied to checkbox's development cycle. You already seem to have a .deb so the packaging work is already done.

That said, while I think we'd all benefit from an independent .deb, based on your description it sounds different enough from "stress" that I'd be OK to include this in checkbox if you prefer that option.

Let me know what you'd like to do. If so, I'll probably test how it fits into the checkbox build process because we may need to do some tweaking there, but we'll get to that after you tell me what you'd like to do.

Revision history for this message
Zygmunt Krynicki (zyga) wrote :

61 + m1 = malloc(sizea * sizeb * sizeof(int));
62 + m2 = malloc(sizeb * sizec * sizeof(int));
63 + r = malloc(sizea * sizec * sizeof(int));
64 + if (!m1 || !m2 || !r) {
65 + fprintf(stderr, "WARNING: Thread %3d could not allocate %lld Mbytes\n",
66 + th_arg->t_thnum, mem_size);
67 + th_arg->t_return = -1;
68 + pthread_exit(NULL);
69 + }

You can leak m2 and m1 ir f fails to allocate. I'd use 'goto out;' and place out: on the first of the three free(); calls below.

review: Needs Fixing
Revision history for this message
Zygmunt Krynicki (zyga) wrote :

if r fails to allocate

Revision history for this message
Zygmunt Krynicki (zyga) wrote :

32 +void float_matrix_mul (double *m1, double *m2, double *r, int row1, int col12, int col2)

This is slightly confusing. Perhaps double_matrix_mul?

Revision history for this message
Zygmunt Krynicki (zyga) wrote :

100 +void *float_loop(void *arg)

Ditto

Revision history for this message
Zygmunt Krynicki (zyga) wrote :

223 + if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE)) {
224 + fprintf(stderr, "ERROR: pthread_attr_setdetachstate() failed\n");
225 + exit(3);
226 + }

JOINABLE is default, you don't need to set it

Revision history for this message
Zygmunt Krynicki (zyga) wrote :

248 +
249 + for (i = 0; i < nthreads; i++) {
250 + THREAD_ARG *arg = t_arg + i;
251 + while (arg->t_return == 0);
252 + if (arg->t_return < 0)
253 + running_threads--;
254 + }

What is this busy loop for exactly?

review: Needs Information
Revision history for this message
Zygmunt Krynicki (zyga) wrote :

168 + pthread_attr_t attr;

217 +
218 + if (pthread_attr_init(&attr)) {
219 + fprintf(stderr, "ERROR: pthread_attr_init() failed\n");
220 + exit(2);
221 + }
222 +
223 + if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE)) {
224 + fprintf(stderr, "ERROR: pthread_attr_setdetachstate() failed\n");
225 + exit(3);
226 + }
227 +

263 +
264 + pthread_attr_destroy(&attr);
265 +

Since you don't really need those attributes this code can be removed

Revision history for this message
Zygmunt Krynicki (zyga) wrote :

Please fix the stuff I mentioned (or reply why it should stay as-is). Thanks

review: Needs Fixing
Revision history for this message
Zygmunt Krynicki (zyga) wrote :

Rejecting due to lack of activity. Please re-propose if you want to.

review: Disapprove

Unmerged revisions

2517. By Manoj Iyer

Test case to stress CPU integer and floating point paths. It also execises CPU path that deals with data and text cache misses. On ARMHF this test was able to cause the CPU core temprature to rise to 50c and a power draw of 13.70Watts.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added file 'checkbox-old/scripts/cpustress.c'
--- checkbox-old/scripts/cpustress.c 1970-01-01 00:00:00 +0000
+++ checkbox-old/scripts/cpustress.c 2013-11-27 18:00:12 +0000
@@ -0,0 +1,263 @@
1/* Author: Manoj Iyer <manoj.iyer@canonical.com */
2
3#include <stdio.h>
4#include <stdlib.h>
5#include <getopt.h>
6#include <errno.h>
7#include <pthread.h>
8
9typedef struct {
10 int t_return;
11 int t_loops;
12 int t_thnum;
13 int t_sizea;
14 int t_sizeb;
15 int t_sizec;
16} THREAD_ARG;
17
18void int_matrix_mul (int *m1, int *m2, int *r, int row1, int col12, int col2)
19{
20 int i, j, k;
21
22 for (i = 0; i < row1; i++)
23 for (j = 0; j < col2; j++)
24 for (k = 0; k < col12; k++)
25 r[i*col2+j] += m1[i*col12+k] * m2[k*col2+j];
26}
27
28void float_matrix_mul (double *m1, double *m2, double *r, int row1, int col12, int col2)
29{
30 int i, j, k;
31
32 for (i = 0; i < row1; i++)
33 for (j = 0; j < col2; j++)
34 for (k = 0; k < col12; k++)
35 r[i*col2+j] += m1[i*col12+k] * m2[k*col2+j];
36}
37
38void *int_loop(void *arg)
39{
40 int i, j, k, l;
41 THREAD_ARG *th_arg = (THREAD_ARG *)arg;
42 int numloops;
43 int sizea, sizeb, sizec;
44 long long mem_size;
45 int sum = 0;
46 int *m1;
47 int *m2;
48 int *r;
49
50 numloops = th_arg->t_loops;
51 sizea = th_arg->t_sizea;
52 sizeb = th_arg->t_sizeb;
53 sizec = th_arg->t_sizec;
54
55 mem_size = (sizea * sizeb + sizeb * sizec + sizea * sizec) *
56 sizeof(int) / 1024 / 1024;
57 m1 = malloc(sizea * sizeb * sizeof(int));
58 m2 = malloc(sizeb * sizec * sizeof(int));
59 r = malloc(sizea * sizec * sizeof(int));
60 if (!m1 || !m2 || !r) {
61 fprintf(stderr, "WARNING: Thread %3d could not allocate %lld Mbytes\n",
62 th_arg->t_thnum, mem_size);
63 th_arg->t_return = -1;
64 pthread_exit(NULL);
65 }
66 th_arg->t_return = 1;
67
68 for (l = 0; l < numloops; l++) {
69 for (i = 0; i < sizea; i++) {
70 for (j = 0; j < sizeb; j++)
71 m1[i*sizeb+j] = i + j;
72 }
73 for (i = 0; i < sizeb; i++) {
74 for (j = 0; j < sizec; j++)
75 m2[i*sizec+j] = i * j;
76 }
77 for (i = 0; i < sizea; i++) {
78 for (j = 0; j < sizec; j++)
79 r[i*sizec+j] = 0.0;
80 }
81 int_matrix_mul(m1, m2, r, sizea, sizeb, sizec);
82 }
83
84 for (i = 0; i < sizea; i++)
85 for (j = 0; j < sizec; j++)
86 sum += r[i*sizec+j];
87
88 fprintf(stdout, "Thread %3d result = %d\n", th_arg->t_thnum, sum);
89 free(m1);
90 free(m2);
91 free(r);
92 pthread_exit(NULL);
93}
94
95
96void *float_loop(void *arg)
97{
98 int i, j, k, l;
99 THREAD_ARG *th_arg = (THREAD_ARG *)arg;
100 int numloops;
101 int sizea, sizeb, sizec;
102 long long mem_size;
103 double sum = 0;
104 double *m1;
105 double *m2;
106 double *r;
107
108 numloops = th_arg->t_loops;
109 sizea = th_arg->t_sizea;
110 sizeb = th_arg->t_sizeb;
111 sizec = th_arg->t_sizec;
112
113 mem_size = (sizea * sizeb + sizeb * sizec + sizea * sizec) *
114 sizeof(int) / 1024 / 1024;
115 m1 = malloc(sizea * sizeb * sizeof(double));
116 m2 = malloc(sizeb * sizec * sizeof(double));
117 r = malloc(sizea * sizec * sizeof(double));
118 if (!m1 || !m2 || !r) {
119 fprintf(stderr, "WARNING: Thread %3d could not allocate %lld Mbytes\n",
120 th_arg->t_thnum, mem_size);
121 th_arg->t_return = -1;
122 pthread_exit(NULL);
123 }
124 th_arg->t_return = 1;
125
126 for (l = 0; l < numloops; l++) {
127 for (i = 0; i < sizea; i++) {
128 for (j = 0; j < sizeb; j++)
129 m1[i*sizeb+j] = i + j;
130 }
131 for (i = 0; i < sizeb; i++) {
132 for (j = 0; j < sizec; j++)
133 m2[i*sizec+j] = i * j;
134 }
135 for (i = 0; i < sizea; i++) {
136 for (j = 0; j < sizec; j++)
137 r[i*sizec+j] = 0.0;
138 }
139 float_matrix_mul(m1, m2, r, sizea, sizeb, sizec);
140 }
141
142 for (i = 0; i < sizea; i++)
143 for (j = 0; j < sizec; j++)
144 sum += r[i*sizec+j];
145
146 fprintf(stdout, "Thread %3d result = %lg\n", th_arg->t_thnum, sum);
147 free(m1);
148 free(m2);
149 free(r);
150 pthread_exit(NULL);
151}
152
153int main (int argc, char **argv)
154{
155 int c = 0;
156 int nthreads = 0;
157 int matrix_size = 0;
158 int nloops = 0;
159 int sizea, sizeb, sizec;
160 int rc,i;
161 int extbufsz;
162 int running_threads;
163 pthread_t *tid;
164 pthread_attr_t attr;
165 THREAD_ARG *t_arg;
166
167 static struct option long_options[] =
168 {
169 {"help", no_argument, 0, 'h'},
170 {"threads", required_argument, 0, 't'},
171 {"matrixsize", required_argument, 0, 'm'},
172 {"loops", required_argument, 0, 'l'},
173 {0, 0, 0, 0}
174 };
175
176
177 int option_index = 0;
178 while ((c = getopt_long (argc, argv, "ht:m:", long_options, &option_index)) != -1 ) {
179
180 switch (c) {
181 case 'h':
182 fprintf(stdout, "%s: help menu here\n", argv[0]);
183 break;
184 case 'l':
185 nloops = atoi(optarg);
186 break;
187 case 'm':
188 matrix_size = atoi(optarg);
189 break;
190 case 't':
191 nthreads = atoi(optarg);
192 break;
193 default:
194 abort();
195 }
196 }
197
198 if (nloops == 0 || matrix_size == 0 || nthreads == 0){
199 fprintf(stdout, "%s: --threads <num threads> --matrixsize <size of matrix> --loops <number of iterations>\n", argv[0]);
200 fprintf(stdout, "%s: --threads 100 --matrixsize 500 --loops 100\n", argv[0]);
201 exit(-1);
202 }
203
204 fprintf (stdout, "number of loops = %d matrix size = %dx%d number of threads = %d\n", nloops, matrix_size, matrix_size, nthreads);
205
206 tid = malloc(nthreads * sizeof(pthread_t));
207 t_arg = malloc(nthreads * sizeof(THREAD_ARG));
208
209 if (!tid || !t_arg) {
210 fprintf(stderr, "ERROR: not enough memory\n");
211 exit (1);
212 }
213
214 if (pthread_attr_init(&attr)) {
215 fprintf(stderr, "ERROR: pthread_attr_init() failed\n");
216 exit(2);
217 }
218
219 if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE)) {
220 fprintf(stderr, "ERROR: pthread_attr_setdetachstate() failed\n");
221 exit(3);
222 }
223
224 running_threads = nthreads;
225
226 for (i = 0; i < nthreads; i++) {
227 THREAD_ARG *arg = t_arg + i;
228 arg->t_loops = nloops;
229 arg->t_sizea = arg->t_sizeb = arg->t_sizec = matrix_size;
230 arg->t_thnum = i + 1;
231 arg->t_return = 0;
232
233 if (i % 2)
234 rc = pthread_create(tid + i, &attr, float_loop, (void *)arg);
235 else
236 rc = pthread_create(tid + i, &attr, int_loop, (void *)arg);
237
238 if (rc) {
239 fprintf(stderr, "ERROR: cannot create thread %d - error code is %d\n", i, rc);
240 exit (4);
241 }
242
243 }
244
245 for (i = 0; i < nthreads; i++) {
246 THREAD_ARG *arg = t_arg + i;
247 while (arg->t_return == 0);
248 if (arg->t_return < 0)
249 running_threads--;
250 }
251
252 for (i = 0; i < nthreads; i++) {
253 rc = pthread_join(tid[i], NULL);
254 if (rc && (rc != ESRCH)) {
255 fprintf(stderr, "ERROR: return code from pthread_join(%d) is %d\n", i, rc);
256 exit (5);
257 }
258 }
259
260 pthread_attr_destroy(&attr);
261
262 exit (0);
263}

Subscribers

People subscribed via source and target branches