1 /*
2   Copyright (C) 2021  The Blosc Developers <blosc@blosc.org>
3   https://blosc.org
4   License: BSD 3-Clause (see LICENSE.txt)
5 
6   Benchmark showing Blosc TRUNC_PREC filter from C code.
7 
8   To compile this program:
9 
10   $ gcc -O3 trunc_prec_schunk.c -o trunc_prec_schunk -lblosc2
11 
12 */
13 
14 #include <stdio.h>
15 #include <stdint.h>
16 #include <assert.h>
17 #include <math.h>
18 #include "blosc2.h"
19 
20 
21 #define KB  1024
22 #define MB  (1024*KB)
23 #define GB  (1024*MB)
24 
25 #define NCHUNKS 200
26 #define CHUNKSIZE (500 * 1000)
27 #define NTHREADS 4
28 
29 
fill_buffer(double * buffer,int nchunk)30 void fill_buffer(double *buffer, int nchunk) {
31   double incx = 10. / (NCHUNKS * CHUNKSIZE);
32 
33   for (int i = 0; i < CHUNKSIZE; i++) {
34     double x = incx * (nchunk * CHUNKSIZE + i);
35     buffer[i] = (x - .25) * (x - 4.45) * (x - 8.95);
36     //buffer[i] = x;
37   }
38 }
39 
40 
main(void)41 int main(void) {
42   blosc2_schunk *schunk;
43   int32_t isize = CHUNKSIZE * sizeof(double);
44   int dsize;
45   int64_t nbytes, cbytes;
46   int nchunk, nchunks = 0;
47   blosc_timestamp_t last, current;
48   double totaltime;
49   float totalsize = (float)(isize * NCHUNKS);
50   double *data_buffer = malloc(CHUNKSIZE * sizeof(double));
51   double *rec_buffer = malloc(CHUNKSIZE * sizeof(double));
52 
53   printf("Blosc version info: %s (%s)\n",
54          BLOSC_VERSION_STRING, BLOSC_VERSION_DATE);
55 
56   /* Initialize the Blosc compressor */
57   blosc_init();
58 
59   /* Create a super-chunk container */
60   blosc2_cparams cparams = BLOSC2_CPARAMS_DEFAULTS;
61   cparams.filters[0] = BLOSC_TRUNC_PREC;
62   cparams.filters_meta[0] = 23;  // treat doubles as floats
63   cparams.typesize = sizeof(double);
64   // DELTA makes compression ratio quite worse in this case
65   //cparams.filters[1] = BLOSC_DELTA;
66   // BLOSC_BITSHUFFLE is not compressing better and it quite slower here
67   //cparams.filters[BLOSC_LAST_FILTER - 1] = BLOSC_BITSHUFFLE;
68   // Good codec params for this dataset
69   cparams.compcode = BLOSC_BLOSCLZ;
70   cparams.clevel = 9;
71   cparams.nthreads = NTHREADS;
72   blosc2_storage storage = {.cparams=&cparams, .contiguous=true};
73   schunk = blosc2_schunk_new(&storage);
74 
75   /* Append the chunks */
76   blosc_set_timestamp(&last);
77   for (nchunk = 0; nchunk < NCHUNKS; nchunk++) {
78     fill_buffer(data_buffer, nchunk);
79     nchunks = blosc2_schunk_append_buffer(schunk, data_buffer, isize);
80   }
81   blosc_set_timestamp(&current);
82   totaltime = blosc_elapsed_secs(last, current);
83   printf("[Compr] Elapsed time:\t %6.3f s."
84                  "  Processed data: %.3f GB (%.3f GB/s)\n",
85          totaltime, totalsize / GB, totalsize / (GB * totaltime));
86 
87   /* Gather some info */
88   nbytes = schunk->nbytes;
89   cbytes = schunk->cbytes;
90   printf("Compression super-chunk: %ld -> %ld (%.1fx)\n",
91          (long)nbytes, (long)cbytes, (1. * nbytes) / cbytes);
92 
93   /* Retrieve and decompress the chunks */
94   blosc_set_timestamp(&last);
95   for (nchunk = 0; nchunk < NCHUNKS; nchunk++) {
96     dsize = blosc2_schunk_decompress_chunk(schunk, nchunk, rec_buffer, isize);
97     if (dsize < 0) {
98       printf("Decompression error.  Error code: %d\n", dsize);
99       return dsize;
100     }
101     assert (dsize == (int)isize);
102   }
103   blosc_set_timestamp(&current);
104   totaltime = blosc_elapsed_secs(last, current);
105   totalsize = (float)(isize * nchunks);
106   printf("[Decompr] Elapsed time:\t %6.3f s."
107                  "  Processed data: %.3f GB (%.3f GB/s)\n",
108          totaltime, totalsize / GB, totalsize / (GB * totaltime));
109 
110   /* Check that all the values are in the precision range */
111   blosc_set_timestamp(&last);
112   for (nchunk = 0; nchunk < NCHUNKS; nchunk++) {
113     dsize = blosc2_schunk_decompress_chunk(schunk, nchunk, (void *) rec_buffer, isize);
114     if (dsize < 0) {
115       printf("Decompression error.  Error code: %d\n", dsize);
116       return dsize;
117     }
118     assert (dsize == (int)isize);
119     fill_buffer(data_buffer, nchunk);
120     for (int i = 0; i < CHUNKSIZE; i++) {
121       if (fabs(data_buffer[i] - rec_buffer[i]) > 1e-5) {
122         printf("Value not in tolerance margin: ");
123         printf("%g - %g: %g, (nchunk: %d, nelem: %d)\n",
124                data_buffer[i], rec_buffer[i],
125                (data_buffer[i] - rec_buffer[i]), nchunk, i);
126         return -1;
127       }
128     }
129   }
130   printf("All data did a good roundtrip!\n");
131 
132   /* Free resources */
133   free(data_buffer);
134   free(rec_buffer);
135   /* Destroy the super-chunk */
136   blosc2_schunk_free(schunk);
137   /* Destroy the Blosc environment */
138   blosc_destroy();
139 
140   return 0;
141 }
142