SCU GPU Wavelet Project
To build:
- You'll need to have CUDA, Java, and Google protocol buffers installed. (See the top of the Makefile)
- If you're using Linux or Cygwin, just run "make".
- If you're using Visual Studio, open a visual studio command prompt and run "make". (this is a batch file that calls "nmake" on Makefile.nmake.
I haven't tried integrating it into the Visual Studio IDE yet.
This project uses its own ".cube" file format. It's a container for 3-dimensional chunks of data. One cube file can contain multiple "cubelets". See "cubelet_file.h" for a brief description of the file format. The goal is to split large input file into many cublets, stored them in one cube file, and then process them all in parallel, outputting to another cube file.
Older code (like "haar") used a file format with the descriptive extension ".data". It stores 2-d data in text or binary form. See "data_io.h" for the format.
Here are some of the tools in this project:
-
WaveletSampleImage.java / convert
This converts between jpeg images and cube files or simple data files. It uses the filename extensions to infer the desired operation.
It is necessary to set the CLASSPATH to include the code for WaveletSampleImage and protobuf, and this is done automatically by the "convert" wrapper script (which is generated by the Makefile). So the "convert" script calls the Java code in WaveletSampleImage.
For example, to convert an image to a cube file:
$ ./convert Images/haleakala_orig.jpg 2048 x 2048 grayscale data written to "Images/haleakala_orig.cube" in 0.024 sec
By default, to make things easier for the wavelet algorithms, this will crop the image to be square, resize it down to the next smaller power of two, and convert it to grayscale.
To convert back to an image:
$ ./convert Images/haleakala_orig.cube Images/haleakala_restored.jpg 2048 x 2048 image written to "Images/haleakala_restored.jpg".
WaveletSampleImage.java also supports "data" files, which was a simplified text or binary format that was a predecessor to cube files.
-
cube
This is a utility for manipulating .cube files. For example, to list the contents of a cube file:
$ ./cube list Images/haleakala_orig.cube Cubelet 0,0,0: 2048x2048x1 of UINT8, 4194304 bytes at 91
This can also be used to extract cubelets from a file, generate a cubelet from raw bytes, split a large cubelet into many smaller ones (with optional overlap), or extract part of one cubelet.
-
test_compress_cpu
Run the compression algorithm on one cubelet using the CPU.
$ ./cube list Images/haleakala_orig.cube Cubelet 0,0,0: 2048x2048x1 of UINT8, 4194304 bytes at 91 $ ./test_compress_cpu Images/haleakala_orig.cube foo.cube Read 2048x2048x1 data file: 15.40 ms cdf97 wavelet transform (11,11,0 steps): 161.56 ms min = -18873.121094, max = 421519.750000, threshold = 1.161753893: 295.86 ms Quantize log: 46.40 ms Huffman summarize frequencies 19.482 ms, build encoding 0.061 ms Huffman encoding: 2118372 bytes, 3.93 bits/pixel, longest encoding = 23 bits Write data file: 50.65 ms Total: 574.08 ms $ ./cube list foo.cube Cubelet 0,0,0: 1x2048x2048 of INT32, 2118372 compressed bytes at 1174
-
test_compress_gpu
Run the compression algorithm on one cubelet using the GPU.
$ ./test_compress_gpu Images/haleakala_orig.cube foo.cube GPU 0: GeForce GTX 1080 Read 2048x2048x1 data file: 8.99 ms CUDA initialize: 88.48 ms Copy to GPU: 3.649 ms Wavelet transform: 7.390 ms (transpose 0.308 ms) Absolute value: 0.264 ms Sort: 2.531 ms min = -18873.113281, max = 421519.750000, threshold = 1.161754727 Quantize: 0.182 ms Frequency count: 0.421 ms Copy from GPU: 6.881 ms Huffman summarize frequencies 18.964 ms, build encoding 0.075 ms Huffman encoding: 2118368 bytes, 3.93 bits/pixel, longest encoding = 23 bits Write data file: 79.27 ms Total: 199.87 ms
-
CubeletViewer.java / cubeview
CubeletViewer is a visualizer to see one cubelet in a cube file. "cubeview" is a Makefile-generated wrapper script that sets the classpath for CubeletViewer.
-
haar.cu
This is older code that only supports the ".data" 2-d format. This implements the Haar discrete wavelet transform on a 2-d data file. Give it an input data file and an output data file, and it performs the 2-d transform. Add the "-inverse" command line flag and it performs the inverse. By default it will just do a single step of the transform. Add an integer argument after the filenames to specify a different number of steps.
It does every transform on the CPU and the GPU, and compares the timing and the results. The implementations of each are in dwt_cpu.cc and dwt_gpu.cu. If the CPU and GPU versions are very different, rather than writing the output file, it writes the output of each to "err_cpu.data" and "err_gpu.data".
Example:
% java WaveletSampleImage Images/hubble4096.jpg hubble.data 4096 x 4096 grayscale data written to "hubble.data" in 1.730 sec % ./haar hubble.data hubble2.data 3 Reading hubble.data...4096 x 4096 GPU 0: GeForce GTX 680 CPU: 593.847 ms Tile size 32x32 Time elapsed creating GPU tasks: 0.164 ms Times: Copy data to GPU: 10.275 ms Transform time: 4.359 ms (6 calls) Copy data from GPU: 10.359 ms CUDA: 25.003168 ms Wrote hubble2.data % java WaveletSampleImage hubble2.data 4096 x 4096 image written to "hubble2.jpg". % ./haar -inverse hubble2.data hubble3.data 3 Reading hubble2.data...4096 x 4096 GPU 0: GeForce GTX 680 CPU: 601.198 ms Tile size 32x32 Time elapsed creating GPU tasks: 0.150 ms Times: Copy data to GPU: 10.275 ms Transform time: 4.290 ms (6 calls) Copy data from GPU: 10.153 ms CUDA: 24.728704 ms Wrote hubble3.data % java WaveletSampleImage hubble3.data 4096 x 4096 image written to "hubble3.jpg".