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
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 */
18
22
#include <string.h>
19
23
#include <stdlib.h>
24
#include "stream_int.h"
27
#ifdef HAVE_STREAM_LIB
28
#include "stream_lib.h"
26
34
unsigned long msize;
36
/* Should get this from cpuinfo, but on !x86 it's not there */
58
#ifdef HAVE_STREAM_LIB
67
void output(char *title, char *result)
69
if (!isspace(delim[0]))
70
printf("%s%s%s\n", title,delim, result);
72
printf("%-42s%s\n", title, result);
76
#ifdef HAVE_STREAM_LIB
48
77
void do_stream(char *name, unsigned char *mem)
80
char title[100], buf[100];
52
81
double res[STREAM_NRESULTS];
53
82
stream_verbose = 0;
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);
87
for (i = 0; i < STREAM_NRESULTS; i++) {
90
sprintf(buf+strlen(buf), "%s%s%.2f%sMB/s",
91
stream_names[i], delim, res[i], delim);
98
static inline unsigned long long timerfold(struct timeval *tv)
100
return tv->tv_sec * 1000000ULL + tv->tv_usec;
65
105
void memtest(char *name, unsigned char *mem)
68
unsigned long start, end, max, min, sum;
108
struct timeval start, end, res;
109
unsigned long long max, min, sum, r;
70
111
char title[128], result[128];
113
#ifdef HAVE_STREAM_LIB
72
114
if (thistest == STREAM) {
73
115
do_stream(name, mem);
80
123
for (i = 0; i < LOOPS; i++) {
81
124
switch (thistest) {
126
gettimeofday(&start,NULL);
84
127
memset(mem, 0xff, msize);
128
gettimeofday(&end,NULL);
130
gettimeofday(&start,NULL);
88
131
memcpy(mem, mem + msize/2, msize/2);
132
gettimeofday(&end,NULL);
93
136
/* simple kernel to just fetch cachelines and write them back.
94
137
will trigger hardware prefetch */
96
for (k = 0; k < msize; k+=64)
138
gettimeofday(&start,NULL);
139
for (k = 0; k < msize; k+=CACHELINESIZE)
141
gettimeofday(&end,NULL);
102
/* simple kernel to avoid hardware prefetch */
104
for (k = msize-5; k > 0; k-=64)
145
gettimeofday(&start,NULL);
146
for (k = msize-5; k > 0; k-=CACHELINESIZE)
148
gettimeofday(&end,NULL);
154
/* only use power of two msize to avoid division */
155
for (w = 1; w < msize; w <<= 1)
160
gettimeofday(&start,NULL);
161
for (k = msize; k > 0; k -= 8)
162
mem[mt_random() & w]++;
163
gettimeofday(&end,NULL);
110
start = end = 0; /* just to quiten gcc */
113
if ((end-start) > max) max = end-start;
114
if ((end-start) < min) min = end-start;
171
timersub(&end, &start, &res);
173
if (r > max) max = r;
174
if (r < min) min = r;
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",
120
(sum / LOOPS) / (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",
128
if (!isspace(delim[0]))
129
printf("%s%s%s\n", title,delim, result);
131
printf("%-30s%35s\n", title, result);
190
output(title,result);
134
192
numa_free(mem, msize);
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]);
324
/* duplicated to make numademo standalone */
325
long memsize(char *s)
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;
264
337
int main(int ac, char **av)
339
int simple_tests = 0;
266
341
while (av[1] && av[1][0] == '-') {
267
342
switch (av[1][1]) {