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

Subscribers

People subscribed via source and target branches