~ubuntu-branches/ubuntu/utopic/numactl/utopic

« back to all changes in this revision

Viewing changes to numademo.c

  • Committer: Bazaar Package Importer
  • Author(s): Ian Wienand
  • Date: 2006-01-04 10:25:27 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20060104102527-1seu1f5eafl9iuoc
Tags: 0.9-1
* New upstream
* Most patches accepted into upstream; see upstream changelog or
  debian/patches/README in source package for history

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* Copyright (C) 2003,2004 Andi Kleen, SuSE Labs.
2
 
   Test/demo program for libnuma.
 
2
   Test/demo program for libnuma. This is also a more or less useful benchmark
 
3
   of the NUMA characteristics of your machine. It benchmarks most possible 
 
4
   NUMA policy memory configurations with various benchmarks.
 
5
   Compile standalone with cc -O2 numademo.c -o numademo -lnuma -lm
3
6
 
4
7
   numactl is free software; you can redistribute it and/or
5
8
   modify it under the terms of the GNU General Public
14
17
   You should find a copy of v2 of the GNU General Public License somewhere
15
18
   on your Linux system; if not, write to the Free Software Foundation, 
16
19
   Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
 
20
#define _GNU_SOURCE 1
17
21
#include <stdio.h>
18
22
#include <string.h>
19
23
#include <stdlib.h>
20
24
#include <ctype.h>
 
25
#include <sys/time.h>
21
26
#include "numa.h"
22
 
#include "util.h"
23
 
#include "rdtsc.h"
24
 
#include "stream_int.h"
 
27
#ifdef HAVE_STREAM_LIB
 
28
#include "stream_lib.h"
 
29
#endif
 
30
#ifdef HAVE_MT
 
31
#include "mt.h"
 
32
#endif
25
33
 
26
34
unsigned long msize; 
27
35
 
 
36
/* Should get this from cpuinfo, but on !x86 it's not there */
 
37
enum { 
 
38
        CACHELINESIZE = 64,
 
39
}; 
 
40
 
28
41
enum test { 
29
42
        MEMSET = 0,
30
43
        MEMCPY,
31
44
        FORWARD,
32
45
        BACKWARD,
33
46
        STREAM,
 
47
        RANDOM,
34
48
} thistest;
35
49
 
36
50
char *delim = " ";
41
55
        "memcpy",
42
56
        "forward",
43
57
        "backward",
 
58
#ifdef HAVE_STREAM_LIB
44
59
        "stream",
 
60
#endif
 
61
#ifdef HAVE_MT
 
62
        "random",
 
63
#endif
45
64
        NULL,
46
65
}; 
47
66
 
 
67
void output(char *title, char *result)
 
68
{
 
69
        if (!isspace(delim[0]))
 
70
                printf("%s%s%s\n", title,delim, result); 
 
71
        else
 
72
                printf("%-42s%s\n", title, result); 
 
73
}
 
74
 
 
75
 
 
76
#ifdef HAVE_STREAM_LIB
48
77
void do_stream(char *name, unsigned char *mem)
49
78
{
50
79
        int i;
51
 
        char title[100];
 
80
        char title[100], buf[100];
52
81
        double res[STREAM_NRESULTS];
53
82
        stream_verbose = 0;
54
83
        stream_init(mem); 
55
84
        stream_test(res);
56
85
        sprintf(title, "%s%s%s", name, delim, "STREAM");
57
 
        printf("%-30s", title);
58
 
        for (i = 0; i < STREAM_NRESULTS; i++) 
59
 
                printf("%s%s%s%.2f", delim, stream_names[i], delim, res[i]); 
60
 
        printf("%sMB/s\n", delim);
 
86
        buf[0] = '\0';
 
87
        for (i = 0; i < STREAM_NRESULTS; i++) { 
 
88
                if (buf[0])
 
89
                        strcat(buf,delim);
 
90
                sprintf(buf+strlen(buf), "%s%s%.2f%sMB/s", 
 
91
                        stream_names[i], delim, res[i], delim);
 
92
        }
 
93
        output(title, buf);
 
94
}
 
95
#endif
 
96
 
 
97
 
 
98
static inline unsigned long long timerfold(struct timeval *tv)
 
99
{
 
100
        return tv->tv_sec * 1000000ULL + tv->tv_usec;
61
101
}
62
102
 
63
103
#define LOOPS 10
64
104
 
65
105
void memtest(char *name, unsigned char *mem)
66
106
67
 
        long k;
68
 
        unsigned long start, end, max, min, sum; 
 
107
        long k, w;
 
108
        struct timeval start, end, res;
 
109
        unsigned long long max, min, sum, r; 
69
110
        int i;
70
111
        char title[128], result[128];
71
112
 
 
113
#ifdef HAVE_STREAM_LIB
72
114
        if (thistest == STREAM) { 
73
115
                do_stream(name, mem);
74
116
                goto out;
75
117
        }
 
118
#endif
76
119
        
77
120
        max = 0; 
78
121
        min = ~0UL; 
80
123
        for (i = 0; i < LOOPS; i++) { 
81
124
                switch (thistest) { 
82
125
                case MEMSET:
83
 
                        rdtsc(start);  
 
126
                        gettimeofday(&start,NULL);
84
127
                        memset(mem, 0xff, msize); 
85
 
                        rdtsc(end); 
 
128
                        gettimeofday(&end,NULL);
86
129
                case MEMCPY: 
87
 
                        rdtsc(start);  
 
130
                        gettimeofday(&start,NULL);
88
131
                        memcpy(mem, mem + msize/2, msize/2); 
89
 
                        rdtsc(end); 
 
132
                        gettimeofday(&end,NULL);
90
133
                        break;
91
134
 
92
135
                case FORWARD: 
93
136
                        /* simple kernel to just fetch cachelines and write them back. 
94
137
                           will trigger hardware prefetch */ 
95
 
                        rdtsc(start);  
96
 
                        for (k = 0; k < msize; k+=64) 
 
138
                        gettimeofday(&start,NULL);
 
139
                        for (k = 0; k < msize; k+=CACHELINESIZE) 
97
140
                                mem[k]++;
98
 
                        rdtsc(end); 
 
141
                        gettimeofday(&end,NULL);
99
142
                        break;
100
143
 
101
144
                case BACKWARD: 
102
 
                        /* simple kernel to avoid hardware prefetch */ 
103
 
                        rdtsc(start);  
104
 
                        for (k = msize-5; k > 0; k-=64) 
 
145
                        gettimeofday(&start,NULL);
 
146
                        for (k = msize-5; k > 0; k-=CACHELINESIZE) 
105
147
                                mem[k]--;
106
 
                        rdtsc(end);
107
 
                        break;
 
148
                        gettimeofday(&end,NULL);
 
149
                        break;
 
150
 
 
151
#ifdef HAVE_MT
 
152
                case RANDOM: 
 
153
                        mt_init(); 
 
154
                        /* only use power of two msize to avoid division */
 
155
                        for (w = 1; w < msize; w <<= 1)
 
156
                                ;
 
157
                        if (w > msize) 
 
158
                                w >>= 1;
 
159
                        w--;
 
160
                        gettimeofday(&start,NULL);
 
161
                        for (k = msize; k > 0; k -= 8) 
 
162
                                mem[mt_random() & w]++;
 
163
                        gettimeofday(&end,NULL);
 
164
                        break;
 
165
#endif
108
166
 
109
167
                default:
110
 
                        start = end = 0; /* just to quiten gcc */
111
168
                        break;
112
169
                } 
113
 
                if ((end-start) > max) max = end-start;
114
 
                if ((end-start) < min) min = end-start;
115
 
                sum += (end-start); 
 
170
 
 
171
                timersub(&end, &start, &res);
 
172
                r = timerfold(&res); 
 
173
                if (r > max) max = r;
 
174
                if (r < min) min = r;
 
175
                sum += r; 
116
176
        } 
117
177
        sprintf(title, "%s%s%s", name, delim, testname[thistest]); 
118
 
        sprintf(result, "avg%s%lu%smin%s%lu%smax%s%lu%scycles/KB",
119
 
                delim,
120
 
                (sum / LOOPS) / (msize/1024), 
121
 
                delim,
122
 
                delim,
123
 
                min / (msize/1024), 
124
 
                delim,
125
 
                delim,
126
 
                max / (msize/1024),
 
178
#define H(t) (((double)msize) / ((double)t))
 
179
#define D3 delim,delim,delim
 
180
        sprintf(result, "Avg%s%.2f%sMB/s%sMin%s%.2f%sMB/s%sMax%s%.2f%sMB/s",
 
181
                delim,
 
182
                H(sum/LOOPS), 
 
183
                D3,
 
184
                H(min), 
 
185
                D3,
 
186
                H(max),
127
187
                delim);
128
 
        if (!isspace(delim[0]))
129
 
                printf("%s%s%s\n", title,delim, result); 
130
 
        else
131
 
                printf("%-30s%35s\n", title, result); 
132
 
 
 
188
#undef H
 
189
#undef D3
 
190
        output(title,result);
133
191
 out:
134
192
        numa_free(mem, msize); 
135
193
243
301
                numa_set_preferred(i); 
244
302
                memtest("setting correct preferred node", numa_alloc(msize)); 
245
303
                numa_set_preferred(-1); 
246
 
                printf("\n\n\n"); 
 
304
                if (!delim[0])
 
305
                        printf("\n\n\n"); 
247
306
        } 
248
307
 
249
308
        /* numa_run_on_node_mask is not tested */
252
311
void usage(void)
253
312
{
254
313
        int i;
255
 
        printf("usage: numademo [-f] [-c] msize[kmg] {tests}\nNo tests means run all.\n"); 
256
 
        printf("-c output CSV data. -f run even without NUMA API.\n");  
 
314
        printf("usage: numademo [-S] [-f] [-c] msize[kmg] {tests}\nNo tests means run all.\n"); 
 
315
        printf("-c output CSV data. -f run even without NUMA API. -S run stupid tests\n");  
 
316
        printf("power of two msizes prefered\n"); 
257
317
        printf("valid tests:"); 
258
318
        for (i = 0; testname[i]; i++) 
259
319
                printf(" %s", testname[i]); 
261
321
        exit(1);
262
322
}
263
323
 
 
324
/* duplicated to make numademo standalone */
 
325
long memsize(char *s) 
 
326
 
327
        char *end;
 
328
        long length = strtoul(s,&end,0);
 
329
        switch (toupper(*end)) { 
 
330
        case 'G': length *= 1024;  /*FALL THROUGH*/
 
331
        case 'M': length *= 1024;  /*FALL THROUGH*/
 
332
        case 'K': length *= 1024; break;
 
333
        }
 
334
        return length; 
 
335
 
336
 
264
337
int main(int ac, char **av)
265
338
{
 
339
        int simple_tests = 0;
 
340
        
266
341
        while (av[1] && av[1][0] == '-') { 
267
342
                switch (av[1][1]) { 
268
343
                case 'c': 
271
346
                case 'f': 
272
347
                        force = 1;
273
348
                        break;
 
349
                case 'S':
 
350
                        simple_tests = 1;
 
351
                        break;
274
352
                default:
275
353
                        usage(); 
276
354
                        break; 
292
370
 
293
371
        msize = memsize(av[1]); 
294
372
 
 
373
        if (!msize)
 
374
                usage();
 
375
 
 
376
#ifdef HAVE_STREAM_LIB
295
377
        stream_setmem(msize);
 
378
#endif
296
379
 
297
380
        if (av[2] == NULL) { 
298
381
                test(MEMSET); 
299
382
                test(MEMCPY);
300
 
#if 0
301
 
                test(FORWARD);
302
 
                test(BACKWARD);
 
383
                if (simple_tests) { 
 
384
                        test(FORWARD);
 
385
                        test(BACKWARD);
 
386
                }
 
387
#ifdef HAVE_MT
 
388
                test(RANDOM);
303
389
#endif
 
390
#ifdef HAVE_STREAM_LIB
304
391
                test(STREAM); 
 
392
#endif
305
393
        } else {
306
394
                int k;
307
395
                for (k = 2; k < ac; k++) {