source: trunk/src/bench.c @ 77

Revision 77, 6.9 KB checked in by faltet, 3 years ago (diff)

Merged the 'threaded' branch.

That branch is fairly stable now and has been thoroughly tested. From
now on, Blosc will support threads by default. The drawback is that you
will need to use a threads implementatation, but this is only a relative
problem on Windows, where you have to install the pthread-win32 library.

Line 
1/*********************************************************************
2  Small benchmark for testing basic capabilities of Blosc.
3
4  You can select different degrees of 'randomness' in input buffer, as
5  well as external datafiles (uncomment the lines after "For data
6  coming from a file" comment).
7
8  To compile using GCC:
9
10    gcc -O3 -msse2 -o bench bench.c blosc.c blosclz.c shuffle.c
11
12  I'm collecting speeds for different machines, so the output of your
13  benchmarks and your processor specifications are welcome!
14
15  Author: Francesc Alted (faltet@pytables.org)
16
17  See LICENSES/BLOSC.txt for details about copyright and rights to use.
18**********************************************************************/
19
20#include <stdlib.h>
21#include <stdio.h>
22#include <string.h>
23#include <sys/types.h>
24#include <sys/stat.h>
25#include <fcntl.h>
26#ifdef _WIN32
27  #include <time.h>
28#else
29  #include <unistd.h>
30  #include <sys/time.h>
31#endif
32#include <math.h>
33#include "blosc.h"
34
35#define MB  (1024*1024)
36
37/* #define NCHUNKS (100) */
38/* #define NITER  (10)               /\* Number of iterations *\/ */
39#define NCHUNKS (100)
40#define NITER  (10)               /* Number of iterations */
41
42
43#ifdef _WIN32
44#include <windows.h>
45#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
46  #define DELTA_EPOCH_IN_MICROSECS  11644473600000000Ui64
47#else
48  #define DELTA_EPOCH_IN_MICROSECS  11644473600000000ULL
49#endif
50
51struct timezone
52{
53  int  tz_minuteswest; /* minutes W of Greenwich */
54  int  tz_dsttime;     /* type of dst correction */
55};
56
57int gettimeofday(struct timeval *tv, struct timezone *tz)
58{
59  FILETIME ft;
60  unsigned __int64 tmpres = 0;
61  static int tzflag;
62
63  if (NULL != tv)
64  {
65    GetSystemTimeAsFileTime(&ft);
66
67    tmpres |= ft.dwHighDateTime;
68    tmpres <<= 32;
69    tmpres |= ft.dwLowDateTime;
70
71    /*converting file time to unix epoch*/
72    tmpres -= DELTA_EPOCH_IN_MICROSECS;
73    tmpres /= 10;  /*convert into microseconds*/
74    tv->tv_sec = (long)(tmpres / 1000000UL);
75    tv->tv_usec = (long)(tmpres % 1000000UL);
76  }
77
78  if (NULL != tz)
79  {
80    if (!tzflag)
81    {
82      _tzset();
83      tzflag++;
84    }
85    tz->tz_minuteswest = _timezone / 60;
86    tz->tz_dsttime = _daylight;
87  }
88
89  return 0;
90}
91#endif   /* _WIN32 */
92
93
94/* Given two timeval stamps, return the difference in seconds */
95float getseconds(struct timeval last, struct timeval current) {
96  int sec, usec;
97
98  sec = current.tv_sec - last.tv_sec;
99  usec = current.tv_usec - last.tv_usec;
100  return (float)(((double)sec + usec*1e-6)/((double)NITER*NCHUNKS)*1e6);
101}
102
103
104int get_value(int i, int rshift) {
105  int v;
106
107  v = (i<<26)^(i<<18)^(i<<11)^(i<<3)^i;
108  v &= (1 << (32-rshift)) - 1;
109  return v;
110}
111
112
113void init_buffer(void *src, int size, int rshift) {
114  unsigned int i;
115  int *_src = (int *)src;
116
117  /* To have reproducible results */
118  srand(1);
119
120  /* Initialize the original buffer */
121  for (i = 0; i < size/sizeof(int); ++i) {
122    /* Choose one below */
123    //_src[i] = 0;
124    //_src[i] = 0x01010101;
125    //_src[i] = 0x01020304;
126    //_src[i] = i * 1/.3;
127    //_src[i] = i;
128    //_src[i] = rand() >> rshift;
129    _src[i] = get_value(i, rshift);
130  }
131}
132
133
134int main(void) {
135  int nbytes, cbytes;
136  void *src, *srccpy;
137  void **dest[NCHUNKS], *dest2;
138  size_t i, j;
139  struct timeval last, current;
140  float tmemcpy, tshuf, tunshuf;
141  int clevel;
142  unsigned int size = 128*1024;   /* Buffer size */
143  unsigned int elsize = 4;        /* Datatype size */
144  int rshift = 12;                /* For random data */
145  int nthreads = 1;               /* The number of threads */
146  int doshuffle = 1;              /* Shuffle? */
147  unsigned char *orig, *round;
148
149  blosc_set_nthreads(nthreads);
150  //blosc_set_blocksize(64*1024);
151
152  src = malloc(size);
153  srccpy = malloc(size);
154  dest2 = malloc(size);
155
156  /* Initialize buffers */
157  init_buffer(src, size, rshift);
158  memcpy(srccpy, src, size);
159  for (j = 0; j < NCHUNKS; j++) {
160    dest[j] = malloc(size);
161  }
162
163  printf("********************** Setup info *****************************\n");
164  printf("Blosc version: %s (%s)\n", BLOSC_VERSION_STRING, BLOSC_VERSION_DATE);
165  printf("Using random data with %d significant bits (out of 32)\n", 32-rshift);
166  printf("Dataset size: %d bytes\t Type size: %d bytes\n", size, elsize);
167  printf("Shuffle active?  %s\n", doshuffle ? "Yes" : "No");
168  printf("********************** Running benchmarks *********************\n");
169
170  gettimeofday(&last, NULL);
171  for (i = 0; i < NITER; i++) {
172    for (j = 0; j < NCHUNKS; j++) {
173      memcpy(dest[j], src, size);
174    }
175  }
176  gettimeofday(&current, NULL);
177  tmemcpy = getseconds(last, current);
178  printf("memcpy(write):\t\t %6.1f us, %.1f MB/s\n",
179         tmemcpy, size/(tmemcpy*MB/1e6));
180
181  gettimeofday(&last, NULL);
182  for (i = 0; i < NITER; i++) {
183    for (j = 0; j < NCHUNKS; j++) {
184      memcpy(dest2, dest[j], size);
185    }
186  }
187  gettimeofday(&current, NULL);
188  tmemcpy = getseconds(last, current);
189  printf("memcpy(read):\t\t %6.1f us, %.1f MB/s\n",
190         tmemcpy, size/(tmemcpy*MB/1e6));
191
192  for (clevel=1; clevel<10; clevel++) {
193
194    printf("Compression level: %d\n", clevel);
195    //blosc_set_nthreads(clevel);
196
197    gettimeofday(&last, NULL);
198    for (i = 0; i < NITER; i++) {
199      for (j = 0; j < NCHUNKS; j++) {
200        cbytes = blosc_compress(clevel, doshuffle, elsize, size, src, dest[j]);
201      }
202    }
203    gettimeofday(&current, NULL);
204    tshuf = getseconds(last, current);
205    printf("compression(write):\t %6.1f us, %.1f MB/s\t  ",
206           tshuf, size/(tshuf*MB/1e6));
207    printf("Final bytes: %d  ", cbytes);
208    if (cbytes > 0) {
209      printf("Compr ratio: %3.2f", size/(float)cbytes);
210    }
211    printf("\n");
212
213    /* Compressor was unable to compress.  Copy the buffer manually. */
214    if (cbytes == 0) {
215      for (j = 0; j < NCHUNKS; j++) {
216        memcpy(dest[j], src, size);
217      }
218    }
219
220    gettimeofday(&last, NULL);
221    for (i = 0; i < NITER; i++) {
222      for (j = 0; j < NCHUNKS; j++) {
223        if (cbytes == 0) {
224          memcpy(dest2, dest[j], size);
225          nbytes = size;
226        }
227        else {
228          nbytes = blosc_decompress(dest[j], dest2, size);
229        }
230      }
231    }
232    gettimeofday(&current, NULL);
233    tunshuf = getseconds(last, current);
234    printf("decompression(read):\t %6.1f us, %.1f MB/s\t  ",
235           tunshuf, nbytes/(tunshuf*MB/1e6));
236    if (nbytes < 0) {
237      printf("FAILED.  Error code: %d\n", nbytes);
238    }
239    /* printf("Orig bytes: %d\tFinal bytes: %d\n", cbytes, nbytes); */
240
241    /* Check if data has had a good roundtrip */
242    orig = (unsigned char *)srccpy;
243    round = (unsigned char *)dest2;
244    for(i = 0; i<size; ++i){
245      if (orig[i] != round[i]) {
246        printf("\nError: Original data and round-trip do not match in pos %d\n",
247               (int)i);
248        printf("Orig--> %x, round-trip--> %x\n", orig[i], round[i]);
249        goto out;
250      }
251    }
252
253    printf("OK\n");
254
255  } /* End clevel loop */
256
257 out:
258  free(src); free(srccpy); free(dest2);
259  for (i = 0; i < NCHUNKS; i++) {
260    free(dest[i]);
261  }
262
263  /* Free blosc resources */
264  blosc_free_resources();
265
266  return 0;
267}
Note: See TracBrowser for help on using the repository browser.