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(¤t);
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(¤t);
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