#bindings #github #zfp #com-llnl-zfp #cuda #linker

sys zfp-sys

Raw Rust bindings to ZFP (https://github.com/LLNL/zfp)

16 releases

0.1.15 Mar 6, 2024
0.1.14 Dec 17, 2023
0.1.13 Jun 15, 2023
0.1.11 Jul 19, 2022
0.1.4 Feb 20, 2019

#172 in Compression

Download history 21/week @ 2023-12-11 9/week @ 2023-12-18 14/week @ 2023-12-25 15/week @ 2024-01-01 4/week @ 2024-01-15 12/week @ 2024-01-29 23/week @ 2024-02-05 16/week @ 2024-02-12 39/week @ 2024-02-19 45/week @ 2024-02-26 330/week @ 2024-03-04 168/week @ 2024-03-11 112/week @ 2024-03-18

656 downloads per month
Used in 2 crates

MIT license

1.5MB
32K SLoC

C 16K SLoC // 0.1% comments C++ 12K SLoC // 0.1% comments Bitbake 1.5K SLoC FORTRAN Modern 1K SLoC Cython 869 SLoC // 0.0% comments CUDA 396 SLoC // 0.0% comments Python 255 SLoC // 0.3% comments Rust 118 SLoC // 0.2% comments FORTRAN Legacy 83 SLoC Shell 79 SLoC // 0.2% comments Batch 27 SLoC

zfp-sys

Raw Rust bindings to ZFP (https://github.com/LLNL/zfp).

ZFP version 1.0.0+

Starting with the version 0.1.13 older versions of zfp are no longer supported.

CUDA support

Enable the cuda feature to enable GPU offloading by linking with CUDA libraries. See https://zfp.readthedocs.io/en/release0.5.5/execution.html for more information on how this can be used in practice.

Static linking

Add the static feature to the crate dependency to link the zfp library statically. This also removes OpenMP support from the library, to remove the dependency on the dynamically linked OpenMP library.

Example

use zfp_sys::*;

fn compress_array() {
        //based on examples/simple.c
        let nx = 100;
        let ny = 100;
        let nz = 100;

        let mut array: Vec<f64> = vec![0.0; nx * ny * nz];

        for i in 0..nx {
            for j in 0..ny {
                for k in 0..nz {
                    let x = 2.0 * (i as f64) / (nx as f64);
                    let y = 2.0 * (j as f64) / (ny as f64);
                    let z = 2.0 * (k as f64) / (nz as f64);
                    array[i + nx * (j + ny * k)] = (-(x * x + y * y + z * z)).exp();
                }
            }
        }

        println!("original data sample: {:?}", &array[0..nx]);

        //compression
        /* allocate meta data for the 3D array a[nz][ny][nx] */
        let data_type = zfp_type_zfp_type_double;
        let field = unsafe {
            zfp_field_3d(
                array.as_mut_ptr() as *mut std::ffi::c_void,
                data_type,
                nx as usize,
                ny as usize,
                nz as usize,
            )
        };

        /* allocate meta data for a compressed stream */
        let zfp = unsafe { zfp_stream_open(std::ptr::null_mut() as *mut bitstream) };

        /* set compression mode and parameters via one of three functions */
        unsafe { zfp_stream_set_rate(zfp, 8.0, data_type, 3, 0) };
        /*  zfp_stream_set_precision(zfp, precision); */
        //let tolerance = 1.0e-3;
        //unsafe { zfp_stream_set_accuracy(zfp, tolerance) };

        #[cfg(feature = "cuda")]
        {
            let ret = unsafe { zfp_stream_set_execution(zfp, zfp_exec_policy_zfp_exec_cuda) };

            if ret == 0 {
                println!("failed to set the execution policy to zfp_exec_cuda");
                assert!(false);
            }
        }

        /* allocate buffer for compressed data */
        let bufsize = unsafe { zfp_stream_maximum_size(zfp, field) };
        let mut buffer: Vec<u8> = vec![0; bufsize as usize];

        /* associate bit stream with allocated buffer */
        let stream = unsafe { stream_open(buffer.as_mut_ptr() as *mut std::ffi::c_void, bufsize) };
        unsafe {
            zfp_stream_set_bit_stream(zfp, stream);
            zfp_stream_rewind(zfp);
        }

        /* compress array and output compressed stream */
        let zfpsize = unsafe { zfp_compress(zfp, field) };
        if zfpsize == 0 {
            println!("compression failed");
            assert!(false);
        } else {
            let original_size = nx * ny * nz * std::mem::size_of::<f64>();
            let ratio = (original_size as f64) / (zfpsize as f64);

            println!(
                "bufsize: {} bytes, original size: {} bytes, compressed size: {} bytes, ratio: {}",
                bufsize, original_size, zfpsize, ratio
            );
        }

        /* rewind compressed stream and decompress array */
        unsafe { zfp_stream_rewind(zfp) };
        let ret = unsafe { zfp_decompress(zfp, field) };
        if ret == 0 {
            println!("decompression failed");
            assert!(false);
        } else {
            println!("ret: {}", ret);
        }

        println!("decompressed data sample: {:?}", &array[0..nx]);

        /* clean up */
        unsafe {
            zfp_field_free(field);
            zfp_stream_close(zfp);
            stream_close(stream);
        }

        assert!(true);
    }

No runtime deps

~0–2MB
~40K SLoC