source: branches/threaded/src/bench.c @ 59

Revision 59, 6.7 KB checked in by faltet, 3 years ago (diff)

New version that implements a pool of threads for (de-)compression.

The pool avoids the thread initialization time. Also, both compression
and decompression are supported now in threaded mode.

The benchmark has also been updated to mimic more closely its use in
PyTables? computing mode (tables.Expr).

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
40
41#ifdef _WIN32
42#include <windows.h>
43#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
44  #define DELTA_EPOCH_IN_MICROSECS  11644473600000000Ui64
45#else
46  #define DELTA_EPOCH_IN_MICROSECS  11644473600000000ULL
47#endif
48
49struct timezone
50{
51  int  tz_minuteswest; /* minutes W of Greenwich */
52  int  tz_dsttime;     /* type of dst correction */
53};
54
55int gettimeofday(struct timeval *tv, struct timezone *tz)
56{
57  FILETIME ft;
58  unsigned __int64 tmpres = 0;
59  static int tzflag;
60
61  if (NULL != tv)
62  {
63    GetSystemTimeAsFileTime(&ft);
64
65    tmpres |= ft.dwHighDateTime;
66    tmpres <<= 32;
67    tmpres |= ft.dwLowDateTime;
68
69    /*converting file time to unix epoch*/
70    tmpres -= DELTA_EPOCH_IN_MICROSECS;
71    tmpres /= 10;  /*convert into microseconds*/
72    tv->tv_sec = (long)(tmpres / 1000000UL);
73    tv->tv_usec = (long)(tmpres % 1000000UL);
74  }
75
76  if (NULL != tz)
77  {
78    if (!tzflag)
79    {
80      _tzset();
81      tzflag++;
82    }
83    tz->tz_minuteswest = _timezone / 60;
84    tz->tz_dsttime = _daylight;
85  }
86
87  return 0;
88}
89#endif   /* _WIN32 */
90
91
92/* Given two timeval stamps, return the difference in seconds */
93float getseconds(struct timeval last, struct timeval current) {
94  int sec, usec;
95
96  sec = current.tv_sec - last.tv_sec;
97  usec = current.tv_usec - last.tv_usec;
98  return (float)(((double)sec + usec*1e-6)/((double)NITER*NCHUNKS)*1e6);
99}
100
101
102int get_value(int i, int rshift) {
103  int v;
104
105  v = (i<<26)^(i<<18)^(i<<11)^(i<<3)^i;
106  v &= (1 << (32-rshift)) - 1;
107  return v;
108}
109
110
111void init_buffer(void *src, int size, int rshift) {
112  int i, *_src = (int *)src;
113
114  /* To have reproducible results */
115  srand(1);
116
117  /* Initialize the original buffer */
118  for (i = 0; i < size/sizeof(int); ++i) {
119    /* Choose one below */
120    /* _src[i] = 1; */
121    /* _src[i] = 0x01010101; */
122    /* _src[i] = 0x01020304; */
123    /* _src[i] = i * 1/.3; */
124    /* _src[i] = i; */
125    //_src[i] = rand() >> rshift;
126    _src[i] = get_value(i, rshift);
127  }
128}
129
130
131int main(void) {
132  int nbytes, cbytes;
133  void *src, *srccpy;
134  void **dest[NCHUNKS], *dest2;
135  size_t i, j;
136  struct timeval last, current;
137  float tmemcpy, tshuf, tunshuf;
138  int *_src;
139  int *_srccpy;
140  int rshift = 12;                /* For random data */
141  int clevel;
142  int doshuffle = 1;              /* Shuffle? */
143  int fd;
144  int status;
145  unsigned int size = 1024*1024;  /* Buffer size */
146  unsigned int elsize = 8;        /* Datatype size */
147  unsigned char *orig, *round;
148
149  /* The number of threads */
150  blosc_init_threads(4);
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
196    gettimeofday(&last, NULL);
197    for (i = 0; i < NITER; i++) {
198      for (j = 0; j < NCHUNKS; j++) {
199        cbytes = blosc_compress(clevel, doshuffle, elsize, size, src, dest[j]);
200      }
201    }
202    gettimeofday(&current, NULL);
203    tshuf = getseconds(last, current);
204    printf("compression(write):\t %6.1f us, %.1f MB/s\t  ",
205           tshuf, size/(tshuf*MB/1e6));
206    printf("Final bytes: %d  ", cbytes);
207    if (cbytes > 0) {
208      printf("Compr ratio: %3.2f", size/(float)cbytes);
209    }
210    printf("\n");
211
212    /* Compressor was unable to compress.  Copy the buffer manually. */
213    if (cbytes == 0) {
214      for (j = 0; j < NCHUNKS; j++) {
215        memcpy(dest[j], src, size);
216      }
217    }
218
219    gettimeofday(&last, NULL);
220    for (i = 0; i < NITER; i++) {
221      for (j = 0; j < NCHUNKS; j++) {
222        if (cbytes == 0) {
223          memcpy(dest2, dest[j], size);
224          nbytes = size;
225        }
226        else {
227          nbytes = blosc_decompress(dest[j], dest2, size);
228        }
229      }
230    }
231    gettimeofday(&current, NULL);
232    tunshuf = getseconds(last, current);
233    printf("decompression(read):\t %6.1f us, %.1f MB/s\t  ",
234           tunshuf, nbytes/(tunshuf*MB/1e6));
235    if (nbytes < 0) {
236      printf("FAILED.  Error code: %d\n", nbytes);
237    }
238    /* printf("Orig bytes: %d\tFinal bytes: %d\n", cbytes, nbytes); */
239
240    /* Check if data has had a good roundtrip */
241    orig = (unsigned char *)srccpy;
242    round = (unsigned char *)dest2;
243    for(i = 0; i<size; ++i){
244      if (orig[i] != round[i]) {
245        printf("\nError: Original data and round-trip do not match in pos %d\n",
246               (int)i);
247        printf("Orig--> %x, round-trip--> %x\n", orig[i], round[i]);
248        goto out;
249      }
250    }
251
252    printf("OK\n");
253
254  } /* End clevel loop */
255
256 out:
257  free(src); free(srccpy); free(dest2);
258  for (i = 0; i < NITER; i++) {
259    free(dest[i]);
260  }
261  return 0;
262}
Note: See TracBrowser for help on using the repository browser.