robertu94 / libpressio

A library to abstract between different lossless and lossy compressors
Other
30 stars 11 forks source link

Spack installation fails on macOS #28

Closed lindstro closed 1 year ago

lindstro commented 2 years ago

I'm trying to install libpressio and libpressio-tools using spack. While some compressors (e.g., mgard and ndzip) won't build with their default spack recipes, I can in general get libpressio and most compressors to install. However, libpressio-tools depends on OpenMPI--even with ~mpi--which won't install with Apple clang 13.0.0:

==> Installing openmpi-4.1.1-xelfobhkun75wsc3yi5jkoa2v3ztwwxz
==> No binary for openmpi-4.1.1-xelfobhkun75wsc3yi5jkoa2v3ztwwxz found: installing from source
/Users/lindstrom2/research/projects/zfp/spack/lib/spack/spack/target.py:137: UserWarning: microarchitecture specific optimizations are not supported yet on mixed compiler toolchains [check apple-clang@13.0.0 for further details]
  warnings.warn(msg.format(compiler))
==> Using cached archive: /Users/lindstrom2/research/projects/zfp/spack/var/spack/cache/_source-cache/archive/e2/e24f7a778bd11a71ad0c14587a7f5b00e68a71aa5623e2157bafee3d44c07cda.tar.bz2
==> No patches needed for openmpi
==> openmpi: Executing phase: 'autoreconf'
==> openmpi: Executing phase: 'configure'
==> Error: ProcessError: Command exited with status 1:
    '/var/folders/zt/gyqdfjn95l59363mfw0nxtdw00075s/T/lindstrom2/spack-stage/spack-stage-openmpi-4.1.1-xelfobhkun75wsc3yi5jkoa2v3ztwwxz/spack-src/configure' '--prefix=/Users/lindstrom2/research/projects/zfp/spack/opt/spack/darwin-bigsur-skylake/apple-clang-13.0.0/openmpi-4.1.1-xelfobhkun75wsc3yi5jkoa2v3ztwwxz' '--enable-shared' '--disable-silent-rules' '--disable-builtin-atomics' '--enable-static' '--without-pmi' '--with-zlib=/Users/lindstrom2/research/projects/zfp/spack/opt/spack/darwin-bigsur-skylake/apple-clang-13.0.0/zlib-1.2.11-xevvljjwbmyqlp45p465lfqqj7e6kjeg' '--enable-mpi1-compatibility' '--without-verbs' '--without-ucx' '--without-ofi' '--without-psm' '--without-fca' '--without-cma' '--without-knem' '--without-mxm' '--without-psm2' '--without-hcoll' '--without-xpmem' '--without-slurm' '--without-lsf' '--without-loadleveler' '--without-sge' '--without-alps' '--without-tm' '--disable-memchecker' '--with-libevent=/Users/lindstrom2/research/projects/zfp/spack/opt/spack/darwin-bigsur-skylake/apple-clang-13.0.0/libevent-2.1.12-blitnblx4a3l7zk4c5uxvovllggzpdxu' '--with-hwloc=/Users/lindstrom2/research/projects/zfp/spack/opt/spack/darwin-bigsur-skylake/apple-clang-13.0.0/hwloc-2.6.0-zruns75lvlkl6dqsjkcqop363tjfhm5g' '--disable-java' '--disable-mpi-java' '--without-cuda' '--enable-wrapper-rpath' '--disable-wrapper-runpath' '--disable-mpi-cxx' '--disable-cxx-exceptions'

2 errors found in build log:
     354    checking the name lister (/opt/local/bin/nm -B) interface... BSD nm
     355    checking for fgrep... /opt/local/bin/ggrep -F
     356    checking if .proc/endp is needed... no
     357    checking directive for setting text section... .text
     358    checking directive for exporting symbols... .globl
     359    checking for objdump... objdump
  >> 360    checking if .note.GNU-stack is needed... /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/objdump: error: 'con
            ftest.o': Invalid/Unsupported object file format
     361    no
     362    checking suffix for labels... :
     363    checking prefix for global symbol labels... _
     364    checking prefix for lsym labels... L
     365    checking prefix for function in .type...
     366    checking if .size is needed... no

     ...

     386    * execute.  Note that this is likely not a problem with Open MPI,
     387    * but a problem with the local compiler installation.  More
     388    * information (including exactly what command was given to the
     389    * compiler and what error resulted when the command was executed) is
     390    * available in the config.log file in the Open MPI build directory.
     391    **********************************************************************
  >> 392    configure: error: Could not run a simple Fortran program.  Aborting.

So I tried using gcc 12.1.0 instead, which fails to install pig-config:

==> Installing pkg-config-0.29.2-46z7e6xkqumngmccu753lfg4bd434wcu
==> No binary for pkg-config-0.29.2-46z7e6xkqumngmccu753lfg4bd434wcu found: installing from source
==> Using cached archive: /Users/lindstrom2/research/projects/zfp/spack/var/spack/cache/_source-cache/archive/6f/6fc69c01688c9458a57eb9a1664c9aba372ccda420a02bf4429fe610e7e7d591.tar.gz
==> No patches needed for pkg-config
==> pkg-config: Executing phase: 'autoreconf'
==> pkg-config: Executing phase: 'configure'
==> pkg-config: Executing phase: 'build'
==> Error: ProcessError: Command exited with status 2:
    'make' 'V=1'

8 errors found in build log:
     828                     from /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/CoreServi
            ces.framework/Frameworks/OSServices.framework/Headers/CSIdentity.h:43,
     829                     from /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/CoreServi
            ces.framework/Frameworks/OSServices.framework/Headers/OSServices.h:29,
     830                     from /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/CoreServi
            ces.framework/Frameworks/LaunchServices.framework/Headers/IconsCore.h:23,
     831                     from /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/CoreServi
            ces.framework/Frameworks/LaunchServices.framework/Headers/LaunchServices.h:23,
     832                     from /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/CoreServi
            ces.framework/Headers/CoreServices.h:39,
     833                     from gunicollate.c:30:
  >> 834    /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Security.framework/Headers/Auth
            orization.h:193:14: error: variably modified 'bytes' at file scope
     835      193 |         char bytes[kAuthorizationExternalFormLength];
     836          |              ^~~~~
  >> 837    make[6]: *** [libglib_2_0_la-gunicollate.lo] Error 1
  >> 838    make[5]: *** [all-recursive] Error 1
  >> 839    make[4]: *** [all] Error 2
  >> 840    make[3]: *** [all-recursive] Error 1
  >> 841    make[2]: *** [all] Error 2
  >> 842    make[1]: *** [all-recursive] Error 1
  >> 843    make: *** [all] Error 2

There's also a dependency on git (not sure which package needs it) that similarly fails. Building with gcc 12.1.0 fails for other reasons.

Is there a known toolchain, process, or set of spack options that will allow a spack install on macOS?

robertu94 commented 2 years ago

@lindstro thanks for reaching out and using LibPressio. a few comments:

I don't have an ability to test on MacOS, but I'll do my best.

OpenMPI is probably brought in by hdf5. You need to build LibPressio '^ hdf5~mpi' to get a build of LibPressio tools without any MPI dependency if you can't get MPI to build. You can debug why a package gets pulled in with spack spec. A slightly better fix is to make HDF5 an optional dependency not required by default, but IMHO having it by default leads to better user experience with the CLI.

For MGARD try '^ mgard@robertu94+cuda' to your LibPressio install. This has a few extra commits to fix things on various compilers I've found. Unfortunately CUDA doesn't seem to be optional for MGARD. If this works for you I'll change the dependency in LibPressio to pull this version when mgard is requested.

In my experience NDZIP requires a really new gcc compiler, and your compiler may not be new or gnu enough for it to work. I'll do some testing and add a conflicts clause so at least you get a better error message.

The better place for git and openmpi build bugs is the main spack repo. I don't maintain these packages. You might reach out to adamjstewart or the maintainers of these packages (openmpi should have one. I'm not sure about git) because he is the spack dev who uses MacOS the most. You can get a list of maintainers with 'spack maintainers $package'

I'll follow up after the weekend.

robertu94 commented 2 years ago

You might also look at https://spack.readthedocs.io/en/latest/getting_started.html#mixed-toolchains

lindstro commented 2 years ago

@robertu94 Thanks for a quick response. As a Livermoron I guess I should know enough about spack to figure out how to list package dependencies. After a fair amount to tinkering to avoid any openmp and git dependencies, and after removing sperr and tthresh, this is what worked for me:

spack install libpressio-tools~mpi ^ libpressio~mpi+bitgrooming+blosc+digitrounding+fpzip+mgardx+sz+sz3+zfp ^ hdf5~mpi

Regarding the pressio CLI, is there documentation beyond basic usage? Suppose I have n independent 3D data sets of dimensions nx ny nz. Can I compress them all using pressio in a single invocation? I would not want to treat this as a 4D data set when there is no correlation along the fourth dimension. Would some combination of -p and -k do the job?

robertu94 commented 2 years ago

@lindstro yes. To do so you need a compressor that natively supports multiple buffers. I believe there are 4 right now:

You probably also need to use several other plugins (namely a default one called historian) to get the metrics you want. You also will want to enable hierarchical names so you can configure and get results from meta-compressors independently. I believe the setting is like -Q. This will change the names of all the settings you reference.

I can send you an example Monday once I sit down and confirm it works as expected.

There are also the pressio-batch tools which is configured with JSON in LibPressio-tools, but these also require MPI.

If OpenMP is a problem on MacOS, It should be possible to quickly write a meta-compressor in C++ that compresses many buffers independently, and LibPressio will detect it if you LD_PRELOAD a shared library containing such a compressor. It would essentially be a copy of many_independent_threaded with the openmp stuff stripped out. You would also need to rename all instances of many_independed_threaded to something else like many_independent_serial.

robertu94 commented 2 years ago

I checked my advanced examples repo: https://github.com/robertu94/libpressio-interesting-scripts and I don’t currently have one like you suggested, but I’ll add one

lindstro commented 2 years ago

@lindstro yes. To do so you need a compressor that natively supports multiple buffers. I believe there are 4 right now:

  • optzconfig/LibPressio opt (needs MPI I think, could be made optional use +opt on LibPressio-tools) - this won’t do what you want
  • many_independent (needs MPI. Use +mpi on LibPressio)
  • many_independent_threaded (Needs OpenMP. Use +openmp on LibPressio)
  • many_dependent (needs MPI. Use +mpi on LibPressio)

It is not obvious to me why you would need MPI or OpenMP to compress multiple fields. What I'm trying to do is compress the SDRBench QMCPACK data, which consists of 288 independent and uncorrelated 3D fields of dimensions 69 x 69 x 115 each. You don't want to treat this as a single 4D field as the lack of correlation along the outermost dimension will likely have a very negative impact on compression.

You probably also need to use several other plugins (namely a default one called historian) to get the metrics you want.

I can handle the metrics myself. I just want to compress and then decompress the data.

You also will want to enable hierarchical names so you can configure and get results from meta-compressors independently. I believe the setting is like -Q. This will change the names of all the settings you reference.

Not sure I follow.

I can send you an example Monday once I sit down and confirm it works as expected.

Thanks.

There are also the pressio-batch tools which is configured with JSON in LibPressio-tools, but these also require MPI.

If OpenMP is a problem on MacOS, It should be possible to quickly write a meta-compressor in C++ that compresses many buffers independently, and LibPressio will detect it if you LD_PRELOAD a shared library containing such a compressor. It would essentially be a copy of many_independent_threaded with the openmp stuff stripped out. You would also need to rename all instances of many_independed_threaded to something else like many_independent_serial.

Just to be clear, I'm having issues building OpenMPI (not OpenMP) with Spack on macOS. Still, I'd be perfectly happy with a serial tool that does this for a suite of different compressors without having to learn each of their APIs.

robertu94 commented 2 years ago

@lindstro

It is not obvious to me why you would need MPI or OpenMP to compress multiple fields

The work was done to support multiple buffers as part of an effort to run parallel invocations to compressors. Because parallel was our focus, the serial version never was written because you could simply set many_independent_threaded:nthreads=1 (the default) to get serial execution.

What I'm trying to do is compress the SDRBench QMCPACK data, which consists of 288 independent and uncorrelated 3D fields of dimensions 69 x 69 x 115 each. You don't want to treat this as a single 4D field as the lack of correlation along the outermost dimension will likely have a very negative impact on compression

Of course.

I can handle the metrics myself. I just want to compress and then decompress the data

I assume then that you want to write out the decompressed data then. That doesn't happen by default with the CLI. I made sure to include that in the example linked below.

I can send you an example Monday once I sit down and confirm it works as expected.

As promised here is the example of using multiple files

For this script to produce the stderr that it does need LibPressio@0.88.0. I think I introduced a regression in 0.83.0 so you might need to update if you want this part to work. If your writing out the files yourself, any recent version should work. Here is the example stderr:

/1/error_stat:error_stat:average_difference <double> = -2.53908e-07
/1/error_stat:error_stat:average_error <double> = 8.82639e-07
/1/error_stat:error_stat:difference_range <double> = 2e-05
/1/error_stat:error_stat:error_range <double> = 1e-05
/1/error_stat:error_stat:max_error <double> = 1e-05
/1/error_stat:error_stat:max_pw_rel_error <double> = 3.17604e+06
/1/error_stat:error_stat:max_rel_error <double> = 0.00488292
/1/error_stat:error_stat:min_error <double> = 0
/1/error_stat:error_stat:min_pw_rel_error <double> = 6.08522e-08
/1/error_stat:error_stat:min_rel_error <double> = 0
/1/error_stat:error_stat:mse <double> = 3.66235e-12
/1/error_stat:error_stat:n <uint64> = 25000000
/1/error_stat:error_stat:psnr <double> = 60.5888
/1/error_stat:error_stat:rmse <double> = 1.91373e-06
/1/error_stat:error_stat:value_max <double> = 0.00204795
/1/error_stat:error_stat:value_mean <double> = 8.59691e-06
/1/error_stat:error_stat:value_min <double> = 0
/1/error_stat:error_stat:value_range <double> = 0.00204795
/1/error_stat:error_stat:value_std <double> = 5.25875e-05
/1/size:size:bit_rate <double> = 0.249271
/1/size:size:compressed_size <uint64> = 778972
/1/size:size:compression_ratio <double> = 128.374
/1/size:size:decompressed_size <uint64> = 100000000
/1/size:size:uncompressed_size <uint64> = 100000000
/2/error_stat:error_stat:average_difference <double> = -3.00063e-07
/2/error_stat:error_stat:average_error <double> = 8.86213e-07
/2/error_stat:error_stat:difference_range <double> = 2e-05
/2/error_stat:error_stat:error_range <double> = 1e-05
/2/error_stat:error_stat:max_error <double> = 1e-05
/2/error_stat:error_stat:max_pw_rel_error <double> = 2.75124e+29
/2/error_stat:error_stat:max_rel_error <double> = 0.00133229
/2/error_stat:error_stat:min_error <double> = 0
/2/error_stat:error_stat:min_pw_rel_error <double> = 0
/2/error_stat:error_stat:min_rel_error <double> = 0
/2/error_stat:error_stat:mse <double> = 3.46985e-12
/2/error_stat:error_stat:n <uint64> = 25000000
/2/error_stat:error_stat:psnr <double> = 72.1049
/2/error_stat:error_stat:rmse <double> = 1.86275e-06
/2/error_stat:error_stat:value_max <double> = 0.00750586
/2/error_stat:error_stat:value_mean <double> = 1.2405e-05
/2/error_stat:error_stat:value_min <double> = 0
/2/error_stat:error_stat:value_range <double> = 0.00750586
/2/error_stat:error_stat:value_std <double> = 7.87036e-05
/2/size:size:bit_rate <double> = 0.157954
/2/size:size:compressed_size <uint64> = 493606
/2/size:size:compression_ratio <double> = 202.591
/2/size:size:decompressed_size <uint64> = 100000000
/2/size:size:uncompressed_size <uint64> = 100000000

You also will want to enable hierarchical names so you can configure and get results from meta-compressors independently. I believe the setting is like -Q. This will change the names of all the settings you reference.

Not sure I follow.

tl;dr -- it turns you that you won't need this; read on for an explanation anyway.

By default, LibPressio uses a flat namespace for compressor settings. There is also a "path-based" hierarchical version which is turned on by the -Q flag. This becomes important to support what LibPressio calls meta-compressors. One example that illustrates the point is the switch meta-compressor. Imagine that you have two compression schemes that you want to switch between programmatically based on the presence of some feature that appears in the data. Both use ZFP in accuracy mode, but one applies a domain-specific normalization as a pre-processing step which changes the value range. Because of the different ranges of values, you want to be able to configure each ZFP independently so you can set different accuracy levels. You also want to hide the details of this piece-wise compression approach from the user so they just call compress. The switch meta-compressor lets you do this. But then both zfp plugins both export a pressio:abs setting and the name would conflict. By turning on this mode, LibPressio changes the names to something like /pressio/1/zfp:pressio:abs and /pressio/2/zfp:pressio:abs so you can refer to these settings independently.

I thought I would need this feature to configure libpressio's metrics functionality when using many_independent_threaded, but it turns out that it is not needed.

After a fair amount to tinkering to avoid any openmp and git dependencies...

Just to be clear, I'm having issues building OpenMPI (not OpenMP) with Spack on macOS

I judged by the first comment that you also had a problem with OpenMP. Wasn't trying to cause greater confusion.

robertu94 commented 2 years ago

Also it now possible to drop the hdf5 dependency from LibPressio-tools with libpressio-tools~hdf5

robertu94 commented 2 years ago

@lindstro just following up to make sure that you have what you need.

lindstro commented 2 years ago

Thanks for providing the script--I just now saw it. If I understand correctly, it still needs libpressio to be built with OpenMP or OpenMPI. Please confirm.

Also, my goal is to compress multiple fields from a single file, whereas your example handles one field per file. Moreover, this works well enough for two files but would be quite tedious when there are many (hundreds of) fields, as in the QMCPACK example.

In future versions of zfp, we plan to support more than four dimensions as well as specification of which dimensions are correlated. This way, you could compress a single 3D vector field in AoS layout double field[nz][ny][nx][3] by specifying that the innermost (fastest varying) dimension is not correlated. Similarly, you could compress the QMCPACK SoA data float field[288][115][69][69] by specifying that the outermost (slowest varying) dimension is the number of independent fields. You would tell zfp that this is a single 4D array that should be compressed as 288 3D arrays, e.g., by specifying uncorrelated dimensions using negative values (e.g., 69 x 69 x 115 x -288). This would simplify compressing data with zfp, and I was hoping libpressio could provide similar functionality for other compressors as well.

robertu94 commented 2 years ago

@lindstro this is a neat feature (specifying which dims are correlated) in ZFP. In my mind, there are two questions here:

  1. Can LibPressio something expose this? Of course it could. I would imagine the API could be something like zfp:correlated_dims=1,1,2,2,3 (this isn't the exact syntax, but we can store arrays of integers in a setting) indicating that the first two dims are correlated the next two are correlated but not with the first two, and then the last one is not. This would be a patch to the zfp compressor plug-in. We would need to add something like this. We can make something ZFP specific, but encoding it in the dimensions would not fit our API model well; it would be better to use an option to expose this. I'm open to your suggestions here.

  2. What should the API (across compressors) be? This is not clear to me. ZFP is the only one that has such a feature (as far as I know). Once a few more compressors support this, we can add a general api that works across compressors, but we should get some more implementation experience first. When we do, we reserve the namespace pressio: for these general settings.

For compressors that don't natively support this, we could write a "meta-compressor" that would do something generically to provide this kind of functionality on top of compressors that don't. One idea would be to copy the correlated dims into disjoint buffers, run the compressors separately on each, and then concentrate the results with some meta data. But again more implementation experience is needed because it isn't clear what the right choice is here.

MPI or OpenMP

You probably just need OpenMP. We support both as optional dependencies to expose additional features. The script I sent you uses OpenMP. That doesn't mean it has to run in parallel, but that was what the plug-in that enables this was built for. A user could provide their own 3rd party plug-in in their own code that doesn't need either, but this is the version (with OpenMp) that exists today.

lindstro commented 2 years ago

@robertu94 I think you misunderstood what I meant by correlated dimensions. By this, I'm referring to dimensions that exhibit high smoothness (autocorrelation) and along which we should compress the data. For example, a specification +nx -ny -nz +nw would indicate that the 4D array is really ny nz independent, smooth 2D arrays of dimensions nx nw each, and the compressor would be invoked ny * nz times. I'm not suggesting that pairs of dimensions would exhibit additional correlation between them, although that is of course possible. I'm not aware of any compressor that would exploit such pairwise correlation.

The benefit here is that you wouldn't have to reorder the data or set up appropriate strides for ny * nz separate zfp_compress() calls; the compressor would handle that for you.

As for the API, it could be a Boolean array that indicates whether each dimension is smooth or not.

I agree that we could layer this on top of compressors that do not support such a feature. This is easy enough as long as the compressor supports strided access, like zfp does (though the zfp CLI does not yet expose strides). Without that, you'd potentially have to permute the data first so that the smooth dimensions are the fastest varying ones.

robertu94 commented 2 years ago

@lindstro

I think you misunderstood what I meant by correlated dimensions

Yes. I think you are right. What you are proposing is indeed simpler. I still think that only ZFP (maybe image magick) currently would be positioned to take advantage of such a feature efficently because of its unique strided compression feature so I stand by my earlier statement that we should start with enabling this for ZFP only before we standardize it.

I think the shortest path to exposing this kind of functionality would be to

  1. introduce a setting for the ZFP plugin to indicate the compressed data strides (maybe zfp:strides) so that it can be passed down to zfp_compress and zfp_decompress
  2. write a meta compressor (hearafter "smooth_chunks") that would work with any compressor (but for now just ZFP) responsible for creating the meta data describing the "chunks", and invoking the compressor a sufficent number of times. This would expose an option "smooth_chunks:is_dim_smooth" = {false, true, true, true} (we also support kind of option today) to indicate if data was smooth in this way;
  3. if the "smooth_chunks" compressor sees that the compressor has zfp:strides then it could skip the data permutation, but if it doesn't you could fall back to data permuation.

LibPressio allows users to define these kinds of novel compressors for themselves without modifying LibPressio. It would also be reasonable to fork LibPressio, introduce your changes, and send back a PR, and I would be happy to merge it. If there is a compelling scientific use case where a paper could be written or it is needed for a deliverable for say ECP, I would be happy to help someone else do this.

lindstro commented 2 years ago

@robertu94 I agree with all this.

It seems that libpressio is not quite ready to handle an arbitrary number of (uncorrelated) fields, but this proposed feature would be one way of adding such functionality. I'm afraid I don't have enough spare cycles to contribute a solution myself, but if someone has the time to work on this, it would clearly benefit all compressors. For example, SDRBench suggests compressing the 288 independent 3D QMCPACK fields the following suboptimal way:

pressio -b compressor=$COMP -i einspline_288_115_69_69.pre.f32 -d 69 -d 69 -d 33120 -t float -o rel=1e-2  -m time -m size -M all

where 33120 = 288 * 115. In general, this is not the right way to go as there will be sharp discontinuities along the z dimension whenever you traverse different fields. Such an approach works with zfp whenever nz is a multiple of 4 as then blocks don't straddle two different fields, but that is not the case here (115 mod 4 = 3).

Feel free to close this issue for now. Maybe we can revisit it down the road.

robertu94 commented 2 years ago

@lindstro One last thought, It should be possible to use the chucking meta compressor to get some of this functionality. See if this example works for you: https://github.com/robertu94/libpressio-interesting-scripts/blob/5e4cc8fbee732c8b2952cf4ec13977f5886f432b/strides.sh

lindstro commented 2 years ago

This does not work for me; pressio reports failed to read input file. And yes, I changed -i to point to the right path.

Is chunking the name of the compressor? Should it go last (usage is pressio [args] [compressor])? When I change that, I get another error message: non existent option for the compressor : historian:events. How would I combine this meta compressor with an actual compressor like zfp? Again, there's no documentation of the pressio CLI (or at least I couldn't find any), which would be helpful.

Your script hints at a bug in pressio 0.82.3, but as far as I can tell there's no way to query the pressio version. That, too, would be helpful.

robertu94 commented 2 years ago

pressio or pressio -h provide some basic documentation.

pressio -a version prints out the version of the library and the compressor plugins.

pressio -a help $COMP_ID prints help for a compressor.

You can also add -b foo=bar or -m flags to this to get help for metrics and more complete help for meta compressors. A pattern that I use often is pressio -a help chunking then pressio -a help chunking -b chunking:compressor=many_independent_threaded and so on until all options you need are configured.

chucking is the name of a meta-compressor. It takes an input, divides it into chunks (using chunk:size), and passes each chunk to compress_many of the compressor it is configured to use. This compressor uses many_independent_threaded which is a meta compressor that compresses chunks (in parallel using OpenMP when many_independent_threaded:nthreads> 1 and the compressor is pressio:thead_safe >= pressio_thread_safety_multiple) with multiple calls to the compressor that it is configured to use (in this case sz3). I configured sz3 to use the historian metric to calculate and record metrics each time it is called. The metric configured to use is a composite of error_stat, size, and write_debug_inputs the latter of which writes out the decompressed data files using it's io plugin (by default a binary file using the default io method of posix, but other formats like HDF5, numpy, PETSc are possible with the right configuration options and dependencies). The historian makes a record whenever the compressor is cloned (which is done by many_independent_threaded, and decompress_many is called as specified in historian:events.

The order doesn't matter.

The script as it exists today requires libpressio-tools ^ libpressio@0.88.0:+sz3+openmp To use it with zfp you would ensure that libpressio is also +zfp like so libpressio-tools ^ libpressio@0.88.0:+sz3+openmp+zfp

robertu94 commented 2 years ago

@lindstro do you have what you need here? I things are busy with SC coming up.

lindstro commented 2 years ago

I'm afraid I've not yet had a chance to tinker with this. Is the conclusion that it is possible to use the pressio CLI to compress then decompress and output N independent, contiguous fields, where N can be arbitrarily large, i.e., I don't have to repeat arguments N times on the command line? The example script you provided is for a single field; I'm not sure how it illustrates the use case we've been discussing. Any chance you can adapt it to the QMCPACK data, which consists of 288 independent 3D fields?

robertu94 commented 2 years ago

@lindstro

This works for me, and has all of the features that the strides.sh script does.

pressio   chunking   -b chunking:compressor=many_independent_threaded   -b many_independent_threaded:compressor=sz3   -b sz3:metric=historian   -b historian:metrics=composite   -b many_independent_threaded:metric=noop   -b composite:plugins=error_stat   -b composite:plugins=size   -b composite:plugins=write_debug_inputs   -o write_debug_inputs:write_output=true   -o write_debug_inputs:display_paths=true   -o write_debug_inputs:base_path=/tmp/qmc-   -o historian:events=clone   -o historian:events=decompress_many   -o many_independent_threaded:collect_metrics_on_decompression=1   -o many_independent_threaded:preserve_metrics=1   -o pressio:abs=1e-5   -o chunking:size=69   -o chunking:size=69   -o chunking:size=115   -o chunking:size=1   -i ~/git/datasets/qmc-pack/288x115x69x69/einspline_288_115_69_69.pre.f32 -d 69 -d 69 -d 115 -d 288 -t float -W /tmp/qmc.out   -M all -O all

The more minimal version is

pressio   chunking   -b chunking:compressor=many_independent_threaded   -b many_independent_threaded:compressor=sz3 -o pressio:abs=1e-5   -o chunking:size=69   -o chunking:size=69   -o chunking:size=115   -o chunking:size=1   -i ~/git/datasets/qmc-pack/288x115x69x69/einspline_288_115_69_69.pre.f32 -d 69 -d 69 -d 115 -d 288 -t float -W /tmp/qmc.out   -M all -O all

Then the minimal version using ZFP instead (only -b many_independent_threaded:compressor= changes):

pressio   chunking   -b chunking:compressor=many_independent_threaded   -b many_independent_threaded:compressor=zfp -o pressio:abs=1e-5   -o chunking:size=69   -o chunking:size=69   -o chunking:size=115   -o chunking:size=1   -i ~/git/datasets/qmc-pack/288x115x69x69/einspline_288_115_69_69.pre.f32 -d 69 -d 69 -d 115 -d 288 -t float -W /tmp/qmc.out   -M all -O all
lindstro commented 2 years ago

This still gives me a failed to read input file. As detailed above, I installed libpressio using

spack install libpressio-tools~mpi ^ libpressio~mpi+bitgrooming+blosc+digitrounding+fpzip+mgardx+sz+sz3+zfp ^ hdf5~mpi

Maybe you can try to reproduce?

robertu94 commented 2 years ago

@lindstro you are missing +openmp on libpressio which will cause an error message. However, I get a different error message than you when I leave out this variant: non existent option for the compressor : pressio:abs. This should probably be improved to be something more helpful like compressor "many_independent_threaded" does not exist but I would need to plumb that error message up.

You will also need to call spack load after calling spack install if you didn't do that before (spack allows multiple versions to be installed at the same time, so needs a command to choose which one is active).

It might be that the file is not the right size for what we specified, but this gives me the error failed to read input file invalid dims. For me the files is 630,737,280 bytes according to du -b einspline_288_115_69_69.pre.f32 which is sizeof(float) 6969115288.

lindstro commented 2 years ago

The file size is correct. I added +openmp, but I got the same error message. I noticed I had libpressio 0.87 installed. I tried to upgrade to 0.88, but I'm now getting this error: Error: Package 'z-checker-tools' not found. I've already added repo robertu94_packages. Any ideas?

robertu94 commented 1 year ago

@lindstro I wanted to let you know that the remaining issues that I had with the docker container installations are now resolved. a current version of MGARD, SZ3, QoZ, ndzip are now both available in the container. https://github.com/robertu94/libpressio/pkgs/container/libpressio

lindstro commented 1 year ago

@robertu94 Thanks for the update. Working through Docker is a last-resort option for me and not really something that I am willing to use permanently as substitute for my existing shell scripts, which like pressio basically provide a unified "API" for executing different compressors.

It would be great if the macOS issues could be fixed. I just tried reinstalling using the command-line above:

==> Installing bitgroomingz-2022-10-14-ui5b6fkjlxku6k3bv65no6coxghmjgap
...
  >> 51    Undefined symbols for architecture x86_64:
     52      "_deflate", referenced from:
     53          _zlib_compress3 in callZlib.c.o
     54          _zlib_compress5 in callZlib.c.o
     55      "_deflateBound", referenced from:
     56          _zlib_compress5 in callZlib.c.o
     57      "_deflateEnd", referenced from:

     ...
==> Error: Can't extrapolate a URL for version 3.1.7 because package sz3 defines no URLs

I think you had a fix for the SZ3 package but I can't remember what it was. Oddly enough, this error appears even when I leave +sz3 out, in spite of sz3 being off by default. I had to add ~sz3 to get past this.

As before, pressio reports a failed to read input file error.

robertu94 commented 1 year ago

@lindstro I finally got permissions to the use the debugger on the shared m1 development machine at ANL so I was able to figure out these issues.

I've identified a fix for the linking error here for bitgrooming and the spack error for SZ3. I'll submit the fix to Sheng, and then merged get them into upstream spack. I'll ping you when I create the PR.

I've also found a solution to the pressio chunking bug in the example that I posted here. getopt on MacOS has different behavior than what glibc has -- namely, glibc allows the flags and positional arugments to be any order, and macos requires all flags to be passed before all positional arguments. The following command works for me on MacOS:

pressio -b chunking:compressor=many_independent_threaded   -b many_independent_threaded:compressor=zfp -o pressio:abs=1e-5   -o chunking:size=69   -o chunking:size=69   -o chunking:size=115   -o chunking:size=1   -i ~/git/datasets/einspline_288_115_69_69.pre.f32 -d 69 -d 69 -d 115 -d 288 -t float -W /tmp/qmc.out   -M all -O all chunking

(I just moved chunking to the last argument from the second.)

robertu94 commented 1 year ago

BitGrooming Bug:https://github.com/disheng222/BitGroomingZ/pull/2

lindstro commented 1 year ago

@robertu94 Thanks for tracking down the issue. I can confirm that the above command does work for me.