1#include <config.h>
2#include <stdio.h>
3#include <stdlib.h>
4#include <sys/types.h>
5#ifdef HAVE_SYS_TIMES_H
6#  include <sys/times.h>
7#endif
8#include <sys/stat.h>
9#include <assert.h>
10#include <sys/time.h>
11#include <unistd.h> /* for sysconf */
12#ifdef HAVE_SYS_RESOURCE_H
13#  include <sys/resource.h>
14#endif
15#include <nc_tests.h> /* The ERR macro is here... */
16#include <netcdf.h>
17
18#define FILENAME "tst_chunks3.nc"
19
20/*
21 * The following timing macros can be used by including the necessary
22 * declarations with
23 *
24 *     TIMING_DECLS(seconds)
25 *
26 * and surrounding sections of code to be timed with the "statements"
27 *
28 *     TIMING_START
29 *     [code to be timed goes here]
30 *     TIMING_END(seconds)
31 *
32 * The macros assume the user has stored a description of what is
33 * being timed in a 100-char string time_mess, and has included
34 * <sys/times.h> and <sys/resource.h>.  The timing message printed by
35 * TIMING_END is not terminated by a new-line, to permit appending
36 * additional text to that line, so user must at least printf("\n")
37 * after that.
38 */
39
40#define TIMING_DECLS(seconds)        \
41 long TMreps; /* counts repetitions of timed code */ \
42 long TMrepeats; /* repetitions needed to exceed 0.1 second */ \
43 long emic ;  /* elapsed time in microseconds */ \
44 struct rusage ru; \
45 long inboub; \
46        char time_mess[100]; \
47        float seconds;
48
49#define TIMING_START \
50 TMrepeats = 1; \
51 do { \
52     if(getrusage(RUSAGE_SELF, &ru)) { \
53 printf("getrusage failed, returned %d\n", errno);} \
54     emic = (1000000*(ru.ru_utime.tv_sec + ru.ru_stime.tv_sec) \
55      + ru.ru_utime.tv_usec + ru.ru_stime.tv_usec);     \
56     inb = ru.ru_inblock; \
57            oub = ru.ru_oublock; \
58     for(TMreps=0; TMreps < TMrepeatsTMreps++) {
59
60#define TIMING_END(seconds) \
61            } \
62     if(getrusage(RUSAGE_SELF, &ru)) { \
63 printf("getrusage failed, returned %d\n", errno);} \
64     emic = (1000000*(ru.ru_utime.tv_sec + ru.ru_stime.tv_sec) \
65      + ru.ru_utime.tv_usec + ru.ru_stime.tv_usec) - emic; \
66     inb = ru.ru_inblock - inb; \
67            oub = ru.ru_oublock - oub; \
68     TMrepeats *= 2; \
69 } while (emic < 100000.0 ); \
70 seconds = emic / (1000000.0 * TMreps); \
71 printf("%-45.45s %7.2g sec", \
72        time_messseconds);
73
74/* This macro prints an error message with line number and name of
75 * test program. */
76#define ERR1(n) do {   \
77fflush(stdout); /* Make sure our stdout is synced with stderr. */ \
78fprintf(stderr, "Sorry! Unexpected result, %s, line: %d - %s\n", \
79 __FILE____LINE__nc_strerror(n));  \
80return n; \
81} while (0)
82
83#define NC_COMPRESSED 1
84
85void
86parse_args(int argc, char *argv[], /* from command-line invocation */
87    int *deflate_levelp,    /* returned: 0 uncompressed,
88       1-9 compression level */
89    int *shufflep,    /* returned: 1 if shuffle, otherwise 0 */
90    size_t *dims,    /* returned: dimension sizes */
91    size_t *chunks,    /* returned: chunk sizes */
92    size_t *cache_sizep,    /* returned: cache size (bytes) */
93    size_t *cache_nelemsp,  /* returned: cache capacity (chunks) */
94    float *cache_prep)    /* returned: cache preemption policy (0-1) */
95{
96
97    if(argc > 1) {
98 *deflate_levelp = atol(argv[1]);
99 if (*deflate_levelp < 0) {
100     *deflate_levelp = -*deflate_levelp;
101     *shufflep = NC_SHUFFLE;
102 }
103    }
104    if(argc > 2)
105 dims[0] = atol(argv[2]);
106    if(argc > 3)
107 chunks[0] = atol(argv[3]);
108    else
109 chunks[0] = (dims[0]+7)/8;
110    if(argc > 4)
111 dims[1] = atol(argv[4]);
112    else
113 dims[1] = dims[0];
114    if(argc > 5)
115 chunks[1] = atol(argv[5]);
116    else
117 chunks[1] = chunks[0];
118    if(argc > 6)
119 dims[2] = atol(argv[6]);
120    else
121 dims[2] = dims[1];
122    if(argc > 7)
123 chunks[2] = atol(argv[7]);
124    else
125 chunks[2] = chunks[1];
126    if(argc > 8)
127 *cache_sizep = atol(argv[8]);
128    if(argc > 9)
129 *cache_nelemsp = atol(argv[9]);
130    if(argc > 10)
131 *cache_prep = atof(argv[10]);
132    if(argc > 11) {
133 printf("Usage: %s [def_level] [dim1] [chunk1] [dim2] [chunk2] [dim3] [chunk3] [cache_size] [cache_nelems] [cache_pre]\n",
134        argv[0]);
135 exit(1);
136    }
137    return;
138}
139
140void *
141emalloc(size_t bytes) {
142    size_t *memory;
143    memory = malloc(bytes);
144    if(memory == 0) {
145 printf("malloc failed\n");
146 exit(2);
147    }
148    return memory;
149}
150
151
152/* compare contiguous, chunked, and compressed performance */
153int
154main(int argc, char *argv[]) {
155
156    int  stat;  /* return status */
157    int  ncid;  /* netCDF id */
158    int ijk;
159    int dim1iddim2iddim3id;
160    int varid_g;   /* varid for contiguous */
161    int varid_k;   /* varid for chunked */
162    int varid_x;   /* varid for compressed */
163
164    float *varxy, *varxz, *varyz;    /* 2D memory slabs used for I/O */
165    int mm;
166    size_t dims[] = {256, 256, 256}; /* default dim lengths */
167    size_t chunks[] = {32, 32, 32}; /* default chunk sizes */
168    size_t start[3], count[3];
169    float contig_timechunked_timecompressed_timeratio;
170    int deflate_level = 1; /* default compression level, 9 is
171  * better and slower.  If negative,
172  * turn on shuffle filter also. */
173    int shuffle = NC_NOSHUFFLE;
174    size_t cache_size_def;
175    size_t cache_hash_def;
176    float cache_pre_def;
177    size_t cache_size = 0;     /* use library default */
178    size_t cache_hash = 0;     /* use library default */
179    float cache_pre = -1.0f;     /* use library default */
180
181    /* rank (number of dimensions) for each variable */
182#   define RANK_var1 3
183
184    /* variable shapes */
185    int var_dims[RANK_var1];
186
187    TIMING_DECLS(TMsec) ;
188
189    /* From args, get parameters for timing, including variable and
190       chunk sizes.  Negative deflate level means also use shuffle
191       filter. */
192    parse_args(argcargv, &deflate_level, &shuffledims,
193        chunks, &cache_size, &cache_hash, &cache_pre);
194
195    /* get cache defaults, then set cache parameters that are not default */
196    if((stat = nc_get_chunk_cache(&cache_size_def, &cache_hash_def,
197    &cache_pre_def)))
198 ERR1(stat);
199    if(cache_size == 0)
200 cache_size = cache_size_def;
201    if(cache_hash == 0)
202 cache_hash = cache_hash_def;
203    if(cache_pre == -1.0f)
204 cache_pre = cache_pre_def;
205    if((stat = nc_set_chunk_cache(cache_sizecache_hashcache_pre)))
206 ERR1(stat);
207    printf("cache: %3.2f MBytes  %ld objs  %3.2f preempt, ",
208    cache_size/1.e6, cache_hashcache_pre);
209
210    if(deflate_level == 0) {
211 printf("uncompressed        ");
212    } else {
213 printf("compression level %d", deflate_level);
214    }
215    if(shuffle == 1) {
216 printf(", shuffled");
217    }
218    printf("\n\n");
219
220    /* initialize 2D slabs for writing along each axis with phony data */
221    varyz = (float *) emalloc(sizeof(float) * 1 * dims[1] * dims[2]);
222    varxz = (float *) emalloc(sizeof(float) * dims[0] * 1 * dims[2]);
223    varxy = (float *) emalloc(sizeof(float) * dims[0] * dims[1] * 1);
224    mm = 0;
225    for(j = 0; j < dims[1]; j++) {
226 for(k = 0; k < dims[2]; k++) {
227     varyz[mm++] = k + dims[2]*j;
228 }
229    }
230    mm = 0;
231    for(i = 0; i < dims[0]; i++) {
232 for(k = 0; k < dims[2]; k++) {
233     varxz[mm++] = k + dims[2]*i;
234 }
235    }
236    mm = 0;
237    for(i = 0; i < dims[0]; i++) {
238 for(j = 0; j < dims[1]; j++) {
239     varxy[mm++] = j + dims[1]*i;
240 }
241    }
242
243    if((stat = nc_create(FILENAMENC_NETCDF4 | NC_CLASSIC_MODEL, &ncid)))
244 ERR1(stat);
245
246    /* define dimensions */
247    if((stat = nc_def_dim(ncid, "dim1", dims[0], &dim1id)))
248 ERR1(stat);
249    if((stat = nc_def_dim(ncid, "dim2", dims[1], &dim2id)))
250 ERR1(stat);
251    if((stat = nc_def_dim(ncid, "dim3", dims[2], &dim3id)))
252 ERR1(stat);
253
254    /* define variables */
255    var_dims[0] = dim1id;
256    var_dims[1] = dim2id;
257    var_dims[2] = dim3id;
258    if((stat = nc_def_var(ncid, "var_contiguous", NC_FLOATRANK_var1,
259    var_dims, &varid_g)))
260 ERR1(stat);
261    if((stat = nc_def_var(ncid, "var_chunked", NC_FLOATRANK_var1,
262    var_dims, &varid_k)))
263 ERR1(stat);
264    if((stat = nc_def_var(ncid, "var_compressed", NC_FLOATRANK_var1,
265    var_dims, &varid_x)))
266 ERR1(stat);
267
268    if((stat = nc_def_var_chunking(ncidvarid_gNC_CONTIGUOUS, 0)))
269 ERR1(stat);
270
271    if((stat = nc_def_var_chunking(ncidvarid_kNC_CHUNKEDchunks)))
272 ERR1(stat);
273
274    if((stat = nc_def_var_chunking(ncidvarid_xNC_CHUNKEDchunks)))
275 ERR1(stat);
276
277    if (deflate_level != 0) {
278 if((stat = nc_def_var_deflate(ncidvarid_xshuffle,
279        NC_COMPRESSEDdeflate_level)))
280     ERR1(stat);
281    }
282
283    /* leave define mode */
284    if((stat = nc_enddef (ncid)))
285 ERR1(stat);
286
287    /* write each variable one yz slab at a time */
288    start[0] = 0;
289    start[1] = 0;
290    start[2] = 0;
291    count[0] = 1;
292    count[1] = dims[1];
293    count[2] = dims[2];
294
295    sprintf(time_mess,"  contiguous write %3ld %3ld %3ld",
296     1, dims[1], dims[2]);
297    TIMING_START ;
298    for(i = 0; i < dims[0]; i++) {
299 start[0] = i;
300 if((stat = nc_put_vara(ncidvarid_gstartcount, &varyz[0])))
301     ERR1(stat);
302    }
303    TIMING_END(TMsec) ;
304    printf("\n");
305    contig_time = TMsec;
306
307    sprintf(time_mess,"  chunked    write %3ld %3ld %3ld  %3ld %3ld %3ld",
308     1, dims[1], dims[2], chunks[0], chunks[1], chunks[2]);
309    TIMING_START ;
310    for(i = 0; i < dims[0]; i++) {
311 start[0] = i;
312 if((stat = nc_put_vara(ncidvarid_kstartcount, &varyz[0])))
313     ERR1(stat);
314    }
315    TIMING_END(TMsec) ;
316    chunked_time = TMsec;
317    ratio = contig_time/chunked_time;
318    if(ratio >= 1.0)
319 printf(" %5.2g x faster\n", ratio);
320    else
321 printf(" %5.2g x slower\n", 1.0/ratio);
322
323    sprintf(time_mess,"  compressed write %3ld %3ld %3ld  %3ld %3ld %3ld",
324     1, dims[1], dims[2], chunks[0], chunks[1], chunks[2]);
325    TIMING_START ;
326    for(i = 0; i < dims[0]; i++) {
327 start[0] = i;
328 if((stat = nc_put_vara(ncidvarid_xstartcount, &varyz[0])))
329     ERR1(stat);
330    }
331    TIMING_END(TMsec) ;
332    compressed_time = TMsec;
333    ratio = contig_time/compressed_time;
334    if(ratio >= 1.0)
335 printf(" %5.2g x faster\n", ratio);
336    else
337 printf(" %5.2g x slower\n", 1.0/ratio);
338    printf("\n");
339
340    /* write each variable one xz slab at a time */
341    start[0] = 0;
342    start[1] = 0;
343    start[2] = 0;
344    count[0] = dims[0];
345    count[1] = 1;
346    count[2] = dims[2];
347
348    sprintf(time_mess,"  contiguous write %3ld %3ld %3ld",
349     dims[0], 1, dims[2]);
350    TIMING_START ;
351    for(i = 0; i < dims[1]; i++) {
352 start[1] = i;
353 if((stat = nc_put_vara(ncidvarid_gstartcount, &varxz[0])))
354     ERR1(stat);
355    }
356    TIMING_END(TMsec) ;
357    printf("\n");
358    contig_time = TMsec;
359
360    sprintf(time_mess,"  chunked    write %3ld %3ld %3ld  %3ld %3ld %3ld",
361     dims[0], 1, dims[2], chunks[0], chunks[1], chunks[2]);
362    TIMING_START ;
363    for(i = 0; i < dims[1]; i++) {
364 start[1] = i;
365 if((stat = nc_put_vara(ncidvarid_kstartcount, &varxz[0])))
366     ERR1(stat);
367    }
368    TIMING_END(TMsec) ;
369    chunked_time = TMsec;
370    ratio = contig_time/chunked_time;
371    if(ratio >= 1.0)
372 printf(" %5.2g x faster\n", ratio);
373    else
374 printf(" %5.2g x slower\n", 1.0/ratio);
375
376    sprintf(time_mess,"  compressed write %3ld %3ld %3ld  %3ld %3ld %3ld",
377     dims[0], 1, dims[2], chunks[0], chunks[1], chunks[2]);
378    TIMING_START ;
379    for(i = 0; i < dims[1]; i++) {
380 start[1] = i;
381 if((stat = nc_put_vara(ncidvarid_xstartcount, &varxz[0])))
382     ERR1(stat);
383    }
384    TIMING_END(TMsec) ;
385    compressed_time = TMsec;
386    ratio = contig_time/compressed_time;
387    if(ratio >= 1.0)
388 printf(" %5.2g x faster\n", ratio);
389    else
390 printf(" %5.2g x slower\n", 1.0/ratio);
391    printf("\n");
392
393    /* write each variable one xy slab at a time */
394    start[0] = 0;
395    start[1] = 0;
396    start[2] = 0;
397    count[0] = dims[0];
398    count[1] = dims[1];
399    count[2] = 1;
400
401    sprintf(time_mess,"  contiguous write %3ld %3ld %3ld",
402     dims[0], dims[1], 1);
403    TIMING_START ;
404    for(i = 0; i < dims[2]; i++) {
405 start[2] = i;
406 if((stat = nc_put_vara(ncidvarid_gstartcount, &varxy[0])))
407     ERR1(stat);
408    }
409    TIMING_END(TMsec) ;
410    printf("\n");
411    contig_time = TMsec;
412
413    sprintf(time_mess,"  chunked    write %3ld %3ld %3ld  %3ld %3ld %3ld",
414     dims[0], dims[1], 1, chunks[0], chunks[1], chunks[2]);
415    TIMING_START ;
416    for(i = 0; i < dims[2]; i++) {
417 start[2] = i;
418 if((stat = nc_put_vara(ncidvarid_kstartcount, &varxy[0])))
419     ERR1(stat);
420    }
421    TIMING_END(TMsec) ;
422    chunked_time = TMsec;
423    ratio = contig_time/chunked_time;
424    if(ratio >= 1.0)
425 printf(" %5.2g x faster\n", ratio);
426    else
427 printf(" %5.2g x slower\n", 1.0/ratio);
428
429    sprintf(time_mess,"  compressed write %3ld %3ld %3ld  %3ld %3ld %3ld",
430     dims[0], dims[1], 1, chunks[0], chunks[1], chunks[2]);
431    TIMING_START ;
432    for(i = 0; i < dims[2]; i++) {
433 start[2] = i;
434 if((stat = nc_put_vara(ncidvarid_xstartcount, &varxy[0])))
435     ERR1(stat);
436    }
437    TIMING_END(TMsec) ;
438    compressed_time = TMsec;
439    ratio = contig_time/compressed_time;
440    if(ratio >= 1.0)
441 printf(" %5.2g x faster\n", ratio);
442    else
443 printf(" %5.2g x slower\n", 1.0/ratio);
444    printf("\n");
445
446    /* read each variable one yz slab at a time */
447    start[0] = 0;
448    start[1] = 0;
449    start[2] = 0;
450    count[0] = 1;
451    count[1] = dims[1];
452    count[2] = dims[2];
453
454    sprintf(time_mess,"  contiguous  read %3ld %3ld %3ld",
455     1, dims[1], dims[2]);
456    TIMING_START ;
457    for(i = 0; i < dims[0]; i++) {
458 start[0] = i;
459 if((stat = nc_get_vara(ncidvarid_gstartcount, &varyz[0])))
460     ERR1(stat);
461    }
462    TIMING_END(TMsec) ;
463    printf("\n");
464    contig_time = TMsec;
465
466    sprintf(time_mess,"  chunked     read %3ld %3ld %3ld  %3ld %3ld %3ld",
467     1, dims[1], dims[2] , chunks[0], chunks[1], chunks[2]);
468    TIMING_START ;
469    for(i = 0; i < dims[0]; i++) {
470 start[0] = i;
471 if((stat = nc_get_vara(ncidvarid_kstartcount, &varyz[0])))
472     ERR1(stat);
473    }
474    TIMING_END(TMsec) ;
475    chunked_time = TMsec;
476    ratio = contig_time/chunked_time;
477    if(ratio >= 1.0)
478 printf(" %5.2g x faster\n", ratio);
479    else
480 printf(" %5.2g x slower\n", 1.0/ratio);
481
482    sprintf(time_mess,"  compressed  read %3ld %3ld %3ld  %3ld %3ld %3ld",
483     1, dims[1], dims[2] , chunks[0], chunks[1], chunks[2]);
484    TIMING_START ;
485    for(i = 0; i < dims[0]; i++) {
486 start[0] = i;
487 if((stat = nc_get_vara(ncidvarid_xstartcount, &varyz[0])))
488     ERR1(stat);
489    }
490    TIMING_END(TMsec) ;
491    compressed_time = TMsec;
492    ratio = contig_time/compressed_time;
493    if(ratio >= 1.0)
494 printf(" %5.2g x faster\n", ratio);
495    else
496 printf(" %5.2g x slower\n", 1.0/ratio);
497    printf("\n");
498
499    /* read each variable one xz slab at a time */
500    start[0] = 0;
501    start[1] = 0;
502    start[2] = 0;
503    count[0] = dims[0];
504    count[1] = 1;
505    count[2] = dims[2];
506
507    sprintf(time_mess,"  contiguous  read %3ld %3ld %3ld",
508     dims[0], 1, dims[2]);
509    TIMING_START ;
510    for(i = 0; i < dims[1]; i++) {
511 start[1] = i;
512 if((stat = nc_get_vara(ncidvarid_gstartcount, &varxz[0])))
513     ERR1(stat);
514    }
515    TIMING_END(TMsec) ;
516    printf("\n");
517    contig_time = TMsec;
518
519    sprintf(time_mess,"  chunked     read %3ld %3ld %3ld  %3ld %3ld %3ld",
520     dims[0], 1, dims[2], chunks[0], chunks[1], chunks[2]);
521    TIMING_START ;
522    for(i = 0; i < dims[1]; i++) {
523 start[1] = i;
524 if((stat = nc_get_vara(ncidvarid_kstartcount, &varxz[0])))
525     ERR1(stat);
526    }
527    TIMING_END(TMsec) ;
528    chunked_time = TMsec;
529    ratio = contig_time/chunked_time;
530    if(ratio >= 1.0)
531 printf(" %5.2g x faster\n", ratio);
532    else
533 printf(" %5.2g x slower\n", 1.0/ratio);
534
535    sprintf(time_mess,"  compressed  read %3ld %3ld %3ld  %3ld %3ld %3ld",
536     dims[0], 1, dims[2], chunks[0], chunks[1], chunks[2]);
537    TIMING_START ;
538    for(i = 0; i < dims[1]; i++) {
539 start[1] = i;
540 if((stat = nc_get_vara(ncidvarid_xstartcount, &varxz[0])))
541     ERR1(stat);
542    }
543    TIMING_END(TMsec) ;
544    compressed_time = TMsec;
545    ratio = contig_time/compressed_time;
546    if(ratio >= 1.0)
547 printf(" %5.2g x faster\n", ratio);
548    else
549 printf(" %5.2g x slower\n", 1.0/ratio);
550    printf("\n");
551
552    /* read variable one xy slab at a time */
553    start[0] = 0;
554    start[1] = 0;
555    start[2] = 0;
556    count[0] = dims[0];
557    count[1] = dims[1];
558    count[2] = 1;
559
560    sprintf(time_mess,"  contiguous  read %3ld %3ld %3ld",
561     dims[0], dims[1], 1);
562    TIMING_START ;
563    for(i = 0; i < dims[2]; i++) {
564 start[2] = i;
565 if((stat = nc_get_vara(ncidvarid_gstartcount, &varxy[0])))
566     ERR1(stat);
567    }
568    TIMING_END(TMsec) ;
569    printf("\n");
570    contig_time = TMsec;
571
572    sprintf(time_mess,"  chunked     read %3ld %3ld %3ld  %3ld %3ld %3ld",
573     dims[0], dims[1], 1, chunks[0], chunks[1], chunks[2]);
574    TIMING_START ;
575    for(i = 0; i < dims[2]; i++) {
576 start[2] = i;
577 if((stat = nc_get_vara(ncidvarid_kstartcount, &varxy[0])))
578     ERR1(stat);
579    }
580    TIMING_END(TMsec) ;
581    chunked_time = TMsec;
582    ratio = contig_time/chunked_time;
583    if(ratio >= 1.0)
584 printf(" %5.2g x faster\n", ratio);
585    else
586 printf(" %5.2g x slower\n", 1.0/ratio);
587
588    sprintf(time_mess,"  compressed  read %3ld %3ld %3ld  %3ld %3ld %3ld",
589     dims[0], dims[1], 1, chunks[0], chunks[1], chunks[2]);
590    TIMING_START ;
591    for(i = 0; i < dims[2]; i++) {
592 start[2] = i;
593 if((stat = nc_get_vara(ncidvarid_xstartcount, &varxy[0])))
594     ERR1(stat);
595    }
596    TIMING_END(TMsec) ;
597    compressed_time = TMsec;
598    ratio = contig_time/compressed_time;
599    if(ratio >= 1.0)
600 printf(" %5.2g x faster\n", ratio);
601    else
602 printf(" %5.2g x slower\n", 1.0/ratio);
603
604    if((stat = nc_close(ncid)))
605 ERR1(stat);
606
607    return 0;
608}


HyperKWIC - Version 7.20DA executed at 11:37 on 27 Oct 2017 | Polyhedron Solutions - INTERNAL USE | COMMERCIAL (Any O/S) SN 4AKIed