Skip to content

Commit c405bd8

Browse files
Merge pull request #241 from oligamiq/master
add rayon feature
2 parents 7f312be + 9b82d38 commit c405bd8

File tree

6 files changed

+79
-16
lines changed

6 files changed

+79
-16
lines changed

.github/workflows/rust.yml

+26-12
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,14 @@ jobs:
1616
- uses: actions/checkout@v2
1717
- name: Cache Cargo Dependencies
1818
uses: Swatinem/[email protected]
19-
- name: Build
20-
run: cargo build --verbose
21-
- name: Run tests
22-
run: cargo test --verbose
19+
- name: Build without default features
20+
run: cargo build --no-default-features --verbose
21+
- name: Run tests without default features
22+
run: cargo test --no-default-features --verbose
23+
- name: Build with rayon feature
24+
run: cargo build --features rayon --verbose
25+
- name: Run tests with rayon feature
26+
run: cargo test --features rayon --verbose
2327

2428

2529
macos:
@@ -31,10 +35,14 @@ jobs:
3135
- uses: actions/checkout@v2
3236
- name: Cache Cargo Dependencies
3337
uses: Swatinem/[email protected]
34-
- name: Build
35-
run: cargo build --verbose
36-
- name: Run tests
37-
run: cargo test --verbose
38+
- name: Build without default features
39+
run: cargo build --no-default-features --verbose
40+
- name: Run tests without default features
41+
run: cargo test --no-default-features --verbose
42+
- name: Build with rayon feature
43+
run: cargo build --features rayon --verbose
44+
- name: Run tests with rayon feature
45+
run: cargo test --features rayon --verbose
3846

3947
verify-msrv:
4048
strategy:
@@ -84,12 +92,18 @@ jobs:
8492
- name: Start Docker
8593
run: sudo systemctl start docker
8694

87-
- name: Cross-Compile project to powerpc-unknown-linux-gnu
88-
run: cross build --target powerpc-unknown-linux-gnu --verbose
95+
- name: Cross-Compile project to powerpc-unknown-linux-gnu without rayon feature
96+
run: cross build --target powerpc-unknown-linux-gnu --no-default-features --verbose
8997

9098
# https://github.com/cross-rs/cross#supported-targets
91-
- name: Cross-Run Tests in powerpc-unknown-linux-gnu using Qemu
92-
run: cross test --target powerpc-unknown-linux-gnu --verbose
99+
- name: Cross-Run Tests in powerpc-unknown-linux-gnu using Qemu without rayon feature
100+
run: cross test --target powerpc-unknown-linux-gnu --no-default-features --verbose
101+
102+
- name: Cross-Compile project to powerpc-unknown-linux-gnu with rayon feature
103+
run: cross build --target powerpc-unknown-linux-gnu --features rayon --verbose
104+
105+
- name: Cross-Run Tests in powerpc-unknown-linux-gnu with rayon feature using Qemu
106+
run: cross test --target powerpc-unknown-linux-gnu --features rayon --verbose
93107

94108
wasm32:
95109
runs-on: ubuntu-latest

Cargo.toml

+18-2
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ half = "2.1.0" # 16 bit float pixel data type
3232
bit_field = "^0.10.1" # exr file version bit flags
3333
miniz_oxide = "^0.8.0" # zip compression for pxr24
3434
smallvec = "^1.7.0" # make cache-friendly allocations TODO profile if smallvec is really an improvement!
35-
rayon-core = "^1.11.0" # threading for parallel compression TODO make this an optional feature?
35+
rayon-core = { version = "^1.11.0", optional = true } # threading for parallel compression
3636
zune-inflate = { version = "^0.2.3", default-features = false, features = ["zlib"] } # zip decompression, faster than miniz_oxide
3737

3838
[dev-dependencies]
@@ -43,23 +43,39 @@ walkdir = "2.3.2" # automatically test things for all files in a directo
4343
rand = "0.8.5" # used for fuzz testing
4444
rayon = "1.5.3" # run tests for many files in parallel
4545

46+
[features]
47+
default = ["rayon"]
48+
49+
# rayon is used for parallel compression
50+
rayon = ["dep:rayon-core"]
51+
52+
[[example]]
53+
name = "7_write_raw_blocks"
54+
required-features = ["rayon"]
55+
56+
[[example]]
57+
name = "8_read_raw_blocks"
58+
required-features = ["rayon"]
4659

4760
[[bench]]
4861
name = "read"
4962
harness = false
63+
required-features = ["rayon"]
5064

5165
[[bench]]
5266
name = "profiling"
5367
harness = false
68+
required-features = ["rayon"]
5469

5570
[[bench]]
5671
name = "write"
5772
harness = false
73+
required-features = ["rayon"]
5874

5975
[[bench]]
6076
name = "pixel_format_conversion"
6177
harness = false
62-
78+
required-features = ["rayon"]
6379

6480
# recommended release settings for max runtime performance
6581
[profile.release]

src/block/reader.rs

+7
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use std::convert::TryFrom;
55
use std::fmt::Debug;
66
use std::io::{Read, Seek};
77
use std::sync::mpsc;
8+
#[cfg(feature = "rayon")]
89
use rayon_core::{ThreadPool, ThreadPoolBuildError};
910

1011
use smallvec::alloc::sync::Arc;
@@ -212,6 +213,7 @@ pub trait ChunksReader: Sized + Iterator<Item=Result<Chunk>> + ExactSizeIterator
212213
OnProgressChunksReader { chunks_reader: self, callback: on_progress, decoded_chunks: 0 }
213214
}
214215

216+
#[cfg(feature = "rayon")]
215217
/// Decompress all blocks in the file, using multiple cpu cores, and call the supplied closure for each block.
216218
/// The order of the blocks is not deterministic.
217219
/// You can also use `parallel_decompressor` to obtain an iterator instead.
@@ -235,6 +237,7 @@ pub trait ChunksReader: Sized + Iterator<Item=Result<Chunk>> + ExactSizeIterator
235237
Ok(())
236238
}
237239

240+
#[cfg(feature = "rayon")]
238241
/// Return an iterator that decompresses the chunks with multiple threads.
239242
/// The order of the blocks is not deterministic.
240243
/// Use `ParallelBlockDecompressor::new` if you want to use your own thread pool.
@@ -380,6 +383,7 @@ impl<R: ChunksReader> SequentialBlockDecompressor<R> {
380383
}
381384
}
382385

386+
#[cfg(feature = "rayon")]
383387
/// Decompress the chunks in a file in parallel.
384388
/// The first call to `next` will fill the thread pool with jobs,
385389
/// starting to decompress the next few blocks.
@@ -399,6 +403,7 @@ pub struct ParallelBlockDecompressor<R: ChunksReader> {
399403
pool: ThreadPool,
400404
}
401405

406+
#[cfg(feature = "rayon")]
402407
impl<R: ChunksReader> ParallelBlockDecompressor<R> {
403408

404409
/// Create a new decompressor. Does not immediately spawn any tasks.
@@ -512,7 +517,9 @@ impl<R: ChunksReader> Iterator for SequentialBlockDecompressor<R> {
512517
fn size_hint(&self) -> (usize, Option<usize>) { self.remaining_chunks_reader.size_hint() }
513518
}
514519

520+
#[cfg(feature = "rayon")]
515521
impl<R: ChunksReader> ExactSizeIterator for ParallelBlockDecompressor<R> {}
522+
#[cfg(feature = "rayon")]
516523
impl<R: ChunksReader> Iterator for ParallelBlockDecompressor<R> {
517524
type Item = Result<UncompressedBlock>;
518525
fn next(&mut self) -> Option<Self::Item> { self.decompress_next_block() }

src/block/writer.rs

+6
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@ use std::io::Seek;
66
use std::iter::Peekable;
77
use std::ops::Not;
88
use std::sync::mpsc;
9+
#[cfg(feature = "rayon")]
910
use rayon_core::{ThreadPool, ThreadPoolBuildError};
1011

1112
use smallvec::alloc::collections::BTreeMap;
1213

1314
use crate::block::UncompressedBlock;
1415
use crate::block::chunk::Chunk;
16+
#[cfg(feature = "rayon")]
1517
use crate::compression::Compression;
1618
use crate::error::{Error, Result, UnitResult, usize_to_u64};
1719
use crate::io::{Data, Tracking, Write};
@@ -80,6 +82,7 @@ pub trait ChunksWriter: Sized {
8082
SequentialBlocksCompressor::new(meta, self)
8183
}
8284

85+
#[cfg(feature = "rayon")]
8386
/// Obtain a new writer that can compress blocks to chunks on multiple threads, which are then passed to this writer.
8487
/// Returns none if the sequential compressor should be used instead (thread pool creation failure or too large performance overhead).
8588
fn parallel_blocks_compressor<'w>(&'w mut self, meta: &'w MetaData) -> Option<ParallelBlocksCompressor<'w, Self>> {
@@ -101,6 +104,7 @@ pub trait ChunksWriter: Sized {
101104
Ok(())
102105
}
103106

107+
#[cfg(feature = "rayon")]
104108
/// Compresses all blocks to the file.
105109
/// The index of the block must be in increasing line order within the header.
106110
/// Obtain iterator with `MetaData::collect_ordered_blocks(...)` or similar methods.
@@ -332,6 +336,7 @@ impl<'w, W> SequentialBlocksCompressor<'w, W> where W: 'w + ChunksWriter {
332336
}
333337

334338
/// Compress blocks to a chunk writer with multiple threads.
339+
#[cfg(feature = "rayon")]
335340
#[derive(Debug)]
336341
#[must_use]
337342
pub struct ParallelBlocksCompressor<'w, W> {
@@ -348,6 +353,7 @@ pub struct ParallelBlocksCompressor<'w, W> {
348353
next_incoming_chunk_index: usize, // used to remember original chunk order
349354
}
350355

356+
#[cfg(feature = "rayon")]
351357
impl<'w, W> ParallelBlocksCompressor<'w, W> where W: 'w + ChunksWriter {
352358

353359
/// New blocks writer. Returns none if sequential compression should be used.

src/image/read/image.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,11 @@ impl<F, L> ReadImage<F, L> where F: FnMut(f64)
2929
pub fn new(read_layers: L, on_progress: F) -> Self {
3030
Self {
3131
on_progress, read_layers,
32-
pedantic: false, parallel: true,
32+
pedantic: false,
33+
#[cfg(not(feature = "rayon"))]
34+
parallel: false,
35+
#[cfg(feature = "rayon")]
36+
parallel: true,
3337
}
3438
}
3539

@@ -120,6 +124,10 @@ impl<F, L> ReadImage<F, L> where F: FnMut(f64)
120124

121125
// TODO propagate send requirement further upwards
122126
if parallel {
127+
#[cfg(not(feature = "rayon"))]
128+
return Err(crate::error::Error::unsupported("parallel decompression requires the rayon feature"));
129+
130+
#[cfg(feature = "rayon")]
123131
block_reader.decompress_parallel(pedantic, |meta_data, block|{
124132
image_collector.read_block(&meta_data.headers, block)
125133
})?;

src/image/write/mod.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,13 @@ impl<'img, WritableLayers> WritableImage<'img, WritableLayers> for &'img Image<W
7373
WriteImageWithOptions {
7474
image: self,
7575
check_compatibility: true,
76+
77+
#[cfg(not(feature = "rayon"))]
78+
parallel: false,
79+
80+
#[cfg(feature = "rayon")]
7681
parallel: true,
82+
7783
on_progress: ignore_progress
7884
}
7985
}
@@ -164,7 +170,13 @@ impl<'img, L, F> WriteImageWithOptions<'img, L, F>
164170
);
165171

166172
let chunk_writer = chunk_writer.on_progress(self.on_progress);
167-
if self.parallel { chunk_writer.compress_all_blocks_parallel(&meta, blocks)?; }
173+
if self.parallel {
174+
#[cfg(not(feature = "rayon"))]
175+
return Err(crate::error::Error::unsupported("parallel compression requires the rayon feature"));
176+
177+
#[cfg(feature = "rayon")]
178+
chunk_writer.compress_all_blocks_parallel(&meta, blocks)?;
179+
}
168180
else { chunk_writer.compress_all_blocks_sequential(&meta, blocks)?; }
169181
/*let blocks_writer = chunk_writer.as_blocks_writer(&meta);
170182

0 commit comments

Comments
 (0)