diff --git a/Cargo.lock b/Cargo.lock index 518cd8d3..23abfa50 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,15 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "415ed64958754dbe991900f3940677e6a7eefb4d7367afd70d642677b0c7d19d" +[[package]] +name = "addr2line" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" +dependencies = [ + "gimli 0.32.3", +] + [[package]] name = "adler2" version = "2.0.1" @@ -29,6 +38,15 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "anes" version = "0.1.6" @@ -74,12 +92,54 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +[[package]] +name = "ash" +version = "0.38.0+1.3.281" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bb44936d800fea8f016d7f2311c6a4f97aebd5dc86f09906139ec848cf3a46f" +dependencies = [ + "libloading 0.8.9", +] + +[[package]] +name = "async-channel" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "atomic_float" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "628d228f918ac3b82fe590352cc719d30664a0c13ca3a60266fe02c7132d480a" + [[package]] name = "autocfg" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +[[package]] +name = "backtrace" +version = "0.3.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-link", +] + [[package]] name = "base64" version = "0.21.7" @@ -98,6 +158,31 @@ version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" +[[package]] +name = "bincode" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36eaf5d7b090263e8150820482d5d93cd964a81e4019913c972f4edcc6edb740" +dependencies = [ + "serde", + "unty", +] + +[[package]] +name = "bit-set" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34ddef2995421ab6a5c779542c81ee77c115206f4ad9d5a8e05f4ff49716a3dd" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71798fca2c1fe1086445a7258a4bc81e6e49dcd24c8d0dd9a1e57395b603f51" + [[package]] name = "bitflags" version = "1.3.2" @@ -172,6 +257,15 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc119b6761ce8b063102502af49043051f81a9bdf242ae06d12e9ea0d92b727a" +[[package]] +name = "block2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" +dependencies = [ + "objc2", +] + [[package]] name = "bumpalo" version = "3.20.2" @@ -181,6 +275,97 @@ dependencies = [ "allocator-api2", ] +[[package]] +name = "burn" +version = "0.1.0" +dependencies = [ + "atomic_float", + "blas-src", + "burn-backend", + "burn-ir", + "burn-std", + "bytemuck", + "bytes", + "const-random", + "itertools 0.14.0", + "libm", + "macerator", + "matrixmultiply", + "ndarray", + "num-traits", + "openblas-src", + "paste", + "rand 0.10.0", + "rayon", + "seq-macro", + "serde", +] + +[[package]] +name = "burn-backend" +version = "0.21.0-pre.2" +source = "git+https://github.com/tracel-ai/burn.git?rev=ed72d2b#ed72d2b125a364aff18aed2a53396c128e01cb42" +dependencies = [ + "burn-std", + "bytemuck", + "cubecl", + "derive-new", + "enumset", + "hashbrown 0.16.1", + "num-traits", + "portable-atomic-util", + "rand 0.10.0", + "rand_distr 0.6.0", + "serde", + "spin", + "thiserror", +] + +[[package]] +name = "burn-ir" +version = "0.21.0-pre.2" +source = "git+https://github.com/tracel-ai/burn.git?rev=ed72d2b#ed72d2b125a364aff18aed2a53396c128e01cb42" +dependencies = [ + "burn-backend", + "hashbrown 0.16.1", + "serde", +] + +[[package]] +name = "burn-std" +version = "0.21.0-pre.2" +source = "git+https://github.com/tracel-ai/burn.git?rev=ed72d2b#ed72d2b125a364aff18aed2a53396c128e01cb42" +dependencies = [ + "bytemuck", + "bytes", + "cubecl-common", + "cubecl-zspace", + "half", + "num-traits", + "serde", + "smallvec", +] + +[[package]] +name = "bytemuck" +version = "1.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "byteorder" version = "1.5.0" @@ -192,6 +377,9 @@ name = "bytes" version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" +dependencies = [ + "portable-atomic", +] [[package]] name = "cast" @@ -224,6 +412,23 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "chacha20" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" +dependencies = [ + "cfg-if", + "cpufeatures", + "rand_core 0.10.0", +] + [[package]] name = "ciborium" version = "0.2.2" @@ -285,12 +490,61 @@ dependencies = [ "cc", ] +[[package]] +name = "codespan-reporting" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af491d569909a7e4dee0ad7db7f5341fef5c614d5b8ec8cf765732aba3cff681" +dependencies = [ + "serde", + "termcolor", + "unicode-width", +] + +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "const-random" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" +dependencies = [ + "const-random-macro", +] + +[[package]] +name = "const-random-macro" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" +dependencies = [ + "getrandom 0.2.17", + "once_cell", + "tiny-keccak", +] + [[package]] name = "constant_time_eq" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b" +[[package]] +name = "convert_case" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "core-foundation" version = "0.10.1" @@ -345,11 +599,11 @@ dependencies = [ "cranelift-control", "cranelift-entity", "cranelift-isle", - "gimli", + "gimli 0.31.1", "hashbrown 0.14.5", "log", "regalloc2", - "rustc-hash", + "rustc-hash 2.1.2", "serde", "smallvec", "target-lexicon", @@ -540,81 +794,591 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" [[package]] -name = "defmac" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5592fca31e96d8a748d03080b58be78c5383617aa4bd89e69f30607d8769891" +name = "cubecl" +version = "0.10.0-pre.2" +source = "git+https://github.com/tracel-ai/cubecl?rev=5b831a3cfac3eca0065fe0dbf57cddf5946d1586#5b831a3cfac3eca0065fe0dbf57cddf5946d1586" +dependencies = [ + "cubecl-core", + "cubecl-cuda", + "cubecl-ir", + "cubecl-runtime", + "cubecl-wgpu", + "half", +] [[package]] -name = "der" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71fd89660b2dc699704064e59e9dba0147b903e85319429e131620d022be411b" +name = "cubecl-common" +version = "0.10.0-pre.2" +source = "git+https://github.com/tracel-ai/cubecl?rev=5b831a3cfac3eca0065fe0dbf57cddf5946d1586#5b831a3cfac3eca0065fe0dbf57cddf5946d1586" dependencies = [ - "pem-rfc7468", - "zeroize", + "backtrace", + "bincode", + "bytemuck", + "bytes", + "cfg-if", + "cfg_aliases", + "derive-new", + "derive_more", + "dirs", + "embassy-futures", + "embassy-time", + "float4", + "float8", + "futures-lite", + "half", + "hashbrown 0.16.1", + "log", + "num-traits", + "oneshot", + "parking_lot", + "portable-atomic", + "portable-atomic-util", + "rand 0.10.0", + "sanitize-filename", + "serde", + "serde_bytes", + "serde_json", + "spin", + "tynm", + "wasm-bindgen-futures", + "web-time", + "xxhash-rust", ] [[package]] -name = "dirs" -version = "6.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" +name = "cubecl-core" +version = "0.10.0-pre.2" +source = "git+https://github.com/tracel-ai/cubecl?rev=5b831a3cfac3eca0065fe0dbf57cddf5946d1586#5b831a3cfac3eca0065fe0dbf57cddf5946d1586" dependencies = [ - "dirs-sys", + "bitflags 2.11.0", + "bytemuck", + "cubecl-common", + "cubecl-ir", + "cubecl-macros", + "cubecl-runtime", + "cubecl-zspace", + "derive-new", + "derive_more", + "enumset", + "float-ord", + "half", + "hashbrown 0.16.1", + "log", + "num-traits", + "paste", + "serde", + "serde_json", + "variadics_please", ] [[package]] -name = "dirs-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" +name = "cubecl-cpp" +version = "0.10.0-pre.2" +source = "git+https://github.com/tracel-ai/cubecl?rev=5b831a3cfac3eca0065fe0dbf57cddf5946d1586#5b831a3cfac3eca0065fe0dbf57cddf5946d1586" dependencies = [ - "libc", - "option-ext", - "redox_users", - "windows-sys 0.61.2", + "bytemuck", + "cubecl-common", + "cubecl-core", + "cubecl-opt", + "cubecl-runtime", + "derive-new", + "half", + "itertools 0.14.0", + "log", ] [[package]] -name = "either" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +name = "cubecl-cuda" +version = "0.10.0-pre.2" +source = "git+https://github.com/tracel-ai/cubecl?rev=5b831a3cfac3eca0065fe0dbf57cddf5946d1586#5b831a3cfac3eca0065fe0dbf57cddf5946d1586" +dependencies = [ + "bytemuck", + "cubecl-common", + "cubecl-core", + "cubecl-cpp", + "cubecl-runtime", + "cudarc", + "derive-new", + "half", + "log", + "serde", +] [[package]] -name = "equivalent" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" +name = "cubecl-ir" +version = "0.10.0-pre.2" +source = "git+https://github.com/tracel-ai/cubecl?rev=5b831a3cfac3eca0065fe0dbf57cddf5946d1586#5b831a3cfac3eca0065fe0dbf57cddf5946d1586" +dependencies = [ + "cubecl-common", + "cubecl-macros-internal", + "derive-new", + "derive_more", + "enumset", + "float-ord", + "fnv", + "foldhash 0.2.0", + "half", + "hashbrown 0.16.1", + "num-traits", + "portable-atomic", + "serde", + "variadics_please", +] [[package]] -name = "errno" -version = "0.3.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +name = "cubecl-macros" +version = "0.10.0-pre.2" +source = "git+https://github.com/tracel-ai/cubecl?rev=5b831a3cfac3eca0065fe0dbf57cddf5946d1586#5b831a3cfac3eca0065fe0dbf57cddf5946d1586" dependencies = [ - "libc", - "windows-sys 0.61.2", + "cubecl-common", + "darling 0.23.0", + "derive-new", + "ident_case", + "inflections", + "prettyplease", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "fallible-iterator" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" +name = "cubecl-macros-internal" +version = "0.10.0-pre.2" +source = "git+https://github.com/tracel-ai/cubecl?rev=5b831a3cfac3eca0065fe0dbf57cddf5946d1586#5b831a3cfac3eca0065fe0dbf57cddf5946d1586" +dependencies = [ + "darling 0.23.0", + "proc-macro2", + "quote", + "syn", +] [[package]] -name = "fastrand" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +name = "cubecl-opt" +version = "0.10.0-pre.2" +source = "git+https://github.com/tracel-ai/cubecl?rev=5b831a3cfac3eca0065fe0dbf57cddf5946d1586#5b831a3cfac3eca0065fe0dbf57cddf5946d1586" +dependencies = [ + "cubecl-common", + "cubecl-core", + "cubecl-ir", + "float-ord", + "log", + "num", + "petgraph", + "smallvec", + "stable-vec", + "type-map", +] [[package]] -name = "filetime" -version = "0.2.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98844151eee8917efc50bd9e8318cb963ae8b297431495d3f758616ea5c57db" +name = "cubecl-runtime" +version = "0.10.0-pre.2" +source = "git+https://github.com/tracel-ai/cubecl?rev=5b831a3cfac3eca0065fe0dbf57cddf5946d1586#5b831a3cfac3eca0065fe0dbf57cddf5946d1586" +dependencies = [ + "async-channel", + "bytemuck", + "cfg-if", + "cfg_aliases", + "cubecl-common", + "cubecl-ir", + "cubecl-zspace", + "derive-new", + "derive_more", + "dirs", + "enumset", + "hashbrown 0.16.1", + "log", + "md5", + "serde", + "serde_json", + "spin", + "thiserror", + "toml", + "variadics_please", + "wasm-bindgen-futures", + "web-time", +] + +[[package]] +name = "cubecl-wgpu" +version = "0.10.0-pre.2" +source = "git+https://github.com/tracel-ai/cubecl?rev=5b831a3cfac3eca0065fe0dbf57cddf5946d1586#5b831a3cfac3eca0065fe0dbf57cddf5946d1586" +dependencies = [ + "async-channel", + "bytemuck", + "cfg-if", + "cfg_aliases", + "cubecl-common", + "cubecl-core", + "cubecl-ir", + "cubecl-runtime", + "derive-new", + "derive_more", + "half", + "hashbrown 0.16.1", + "log", + "sanitize-filename", + "wgpu", +] + +[[package]] +name = "cubecl-zspace" +version = "0.10.0-pre.2" +source = "git+https://github.com/tracel-ai/cubecl?rev=5b831a3cfac3eca0065fe0dbf57cddf5946d1586#5b831a3cfac3eca0065fe0dbf57cddf5946d1586" +dependencies = [ + "derive-new", + "serde", + "smallvec", +] + +[[package]] +name = "cudarc" +version = "0.19.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f071cd6a7b5d51607df76aa2d426aaabc7a74bc6bdb885b8afa63a880572ad9b" +dependencies = [ + "libloading 0.9.0", +] + +[[package]] +name = "darling" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +dependencies = [ + "darling_core 0.20.11", + "darling_macro 0.20.11", +] + +[[package]] +name = "darling" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" +dependencies = [ + "darling_core 0.21.3", + "darling_macro 0.21.3", +] + +[[package]] +name = "darling" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" +dependencies = [ + "darling_core 0.23.0", + "darling_macro 0.23.0", +] + +[[package]] +name = "darling_core" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_core" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "darling_core" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0" +dependencies = [ + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" +dependencies = [ + "darling_core 0.20.11", + "quote", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" +dependencies = [ + "darling_core 0.21.3", + "quote", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" +dependencies = [ + "darling_core 0.23.0", + "quote", + "syn", +] + +[[package]] +name = "defmac" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5592fca31e96d8a748d03080b58be78c5383617aa4bd89e69f30607d8769891" + +[[package]] +name = "der" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71fd89660b2dc699704064e59e9dba0147b903e85319429e131620d022be411b" +dependencies = [ + "pem-rfc7468", + "zeroize", +] + +[[package]] +name = "derive-new" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cdc8d50f426189eef89dac62fabfa0abb27d5cc008f25bf4156a0203325becc" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "derive_more" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn", + "unicode-xid", +] + +[[package]] +name = "dirs" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.61.2", +] + +[[package]] +name = "dispatch2" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" +dependencies = [ + "bitflags 2.11.0", + "objc2", +] + +[[package]] +name = "dlib" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab8ecd87370524b461f8557c119c405552c396ed91fc0a8eec68679eab26f94a" +dependencies = [ + "libloading 0.8.9", +] + +[[package]] +name = "document-features" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" +dependencies = [ + "litrs", +] + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "embassy-futures" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc2d050bdc5c21e0862a89256ed8029ae6c290a93aecefc73084b3002cdebb01" + +[[package]] +name = "embassy-time" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "592b0c143ec626e821d4d90da51a2bd91d559d6c442b7c74a47d368c9e23d97a" +dependencies = [ + "cfg-if", + "critical-section", + "document-features", + "embassy-time-driver", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "embedded-hal-async", + "futures-core", +] + +[[package]] +name = "embassy-time-driver" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ee71af1b3a0deaa53eaf2d39252f83504c853646e472400b763060389b9fcc9" +dependencies = [ + "document-features", +] + +[[package]] +name = "embedded-hal" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" +dependencies = [ + "nb 0.1.3", + "void", +] + +[[package]] +name = "embedded-hal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" + +[[package]] +name = "embedded-hal-async" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4c685bbef7fe13c3c6dd4da26841ed3980ef33e841cddfa15ce8a8fb3f1884" +dependencies = [ + "embedded-hal 1.0.0", +] + +[[package]] +name = "enumset" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25b07a8dfbbbfc0064c0a6bdf9edcf966de6b1c33ce344bdeca3b41615452634" +dependencies = [ + "enumset_derive", + "serde", +] + +[[package]] +name = "enumset_derive" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f43e744e4ea338060faee68ed933e46e722fb7f3617e722a5772d7e856d8b3ce" +dependencies = [ + "darling 0.21.3", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "event-listener" +version = "5.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" +dependencies = [ + "event-listener", + "pin-project-lite", +] + +[[package]] +name = "fallible-iterator" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "filetime" +version = "0.2.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f98844151eee8917efc50bd9e8318cb963ae8b297431495d3f758616ea5c57db" dependencies = [ "cfg-if", "libc", @@ -627,6 +1391,12 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" +[[package]] +name = "fixedbitset" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" + [[package]] name = "flate2" version = "1.1.9" @@ -637,12 +1407,45 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "float-ord" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce81f49ae8a0482e4c55ea62ebbd7e5a686af544c00b9d090bba3ff9be97b3d" + +[[package]] +name = "float4" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a5404bf31d22893d61cf24d4dda149d8e6b2ff07601c3cb3be651031f61a4ed" + +[[package]] +name = "float8" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2d1f04709a8ac06e8e8042875a3c466cc4832d3c1a18dbcb9dba3c6e83046bc" +dependencies = [ + "half", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + [[package]] name = "foldhash" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + [[package]] name = "foreign-types" version = "0.3.2" @@ -659,11 +1462,46 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] -name = "fractal" -version = "0.1.0" +name = "futures-core" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-io" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" + +[[package]] +name = "futures-lite" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" dependencies = [ - "criterion", - "libm", + "fastrand", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "slab", ] [[package]] @@ -714,14 +1552,89 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "gimli" +version = "0.32.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" + +[[package]] +name = "gl_generator" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d" +dependencies = [ + "khronos_api", + "log", + "xml-rs", +] + +[[package]] +name = "glow" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29038e1c483364cc6bb3cf78feee1816002e127c331a1eec55a4d202b9e1adb5" +dependencies = [ + "js-sys", + "slotmap", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "glutin_wgl_sys" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c4ee00b289aba7a9e5306d57c2d05499b2e5dc427f84ac708bd2c090212cf3e" +dependencies = [ + "gl_generator", +] + +[[package]] +name = "gpu-allocator" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51255ea7cfaadb6c5f1528d43e92a82acb2b96c43365989a28b2d44ee38f8795" +dependencies = [ + "ash", + "hashbrown 0.16.1", + "log", + "presser", + "thiserror", + "windows", +] + +[[package]] +name = "gpu-descriptor" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b89c83349105e3732062a895becfc71a8f921bb71ecbbdd8ff99263e3b53a0ca" +dependencies = [ + "bitflags 2.11.0", + "gpu-descriptor-types", + "hashbrown 0.15.5", +] + +[[package]] +name = "gpu-descriptor-types" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdf242682df893b86f33a73828fb09ca4b2d3bb6cc95249707fc684d27484b91" +dependencies = [ + "bitflags 2.11.0", +] + [[package]] name = "half" version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" dependencies = [ + "bytemuck", "cfg-if", "crunchy", + "num-traits", + "serde", "zerocopy", ] @@ -737,7 +1650,7 @@ version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ - "foldhash", + "foldhash 0.1.5", ] [[package]] @@ -745,6 +1658,13 @@ name = "hashbrown" version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.2.0", + "serde", + "serde_core", +] [[package]] name = "heck" @@ -758,6 +1678,12 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" +[[package]] +name = "hexf-parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" + [[package]] name = "http" version = "1.4.0" @@ -780,6 +1706,12 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "indexmap" version = "2.13.0" @@ -792,6 +1724,12 @@ dependencies = [ "serde_core", ] +[[package]] +name = "inflections" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a257582fdcde896fd96463bf2d40eefea0580021c0712a0e2b028b60b47a837a" + [[package]] name = "is-terminal" version = "0.4.17" @@ -821,22 +1759,78 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" +[[package]] +name = "jni-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41a652e1f9b6e0275df1f15b32661cf0d4b78d4d87ddec5e0c3c20f097433258" +dependencies = [ + "jni-sys 0.4.1", +] + +[[package]] +name = "jni-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" +dependencies = [ + "jni-sys-macros", +] + +[[package]] +name = "jni-sys-macros" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" +dependencies = [ + "quote", + "syn", +] + [[package]] name = "js-sys" version = "0.3.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc4c90f45aa2e6eacbe8645f77fdea542ac97a494bcd117a67df9ff4d611f995" dependencies = [ + "cfg-if", + "futures-util", "once_cell", "wasm-bindgen", ] +[[package]] +name = "khronos-egl" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6aae1df220ece3c0ada96b8153459b67eebe9ae9212258bb0134ae60416fdf76" +dependencies = [ + "libc", + "libloading 0.8.9", + "pkg-config", +] + +[[package]] +name = "khronos_api" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" + [[package]] name = "leb128fmt" version = "0.1.0" @@ -849,6 +1843,26 @@ version = "0.2.183" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" +[[package]] +name = "libloading" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link", +] + +[[package]] +name = "libloading" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "754ca22de805bb5744484a5b151a9e1a8e837d5dc232c2d7d8c2e3492edc8b60" +dependencies = [ + "cfg-if", + "windows-link", +] + [[package]] name = "libm" version = "0.2.16" @@ -864,7 +1878,7 @@ dependencies = [ "bitflags 2.11.0", "libc", "plain", - "redox_syscall", + "redox_syscall 0.7.3", ] [[package]] @@ -873,12 +1887,55 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" +[[package]] +name = "litrs" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + [[package]] name = "log" version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" +[[package]] +name = "macerator" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09e6046277c48f8a44bd6cfae65a1a261cab6622fb6d4a003f5597e4e4f4a661" +dependencies = [ + "bytemuck", + "cfg_aliases", + "half", + "macerator-macros", + "moddef", + "num-traits", + "paste", + "rustc_version", +] + +[[package]] +name = "macerator-macros" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23ee1819976b67f4d782390c55a75c13401c7a988517f7f8e60a33484dc2e00a" +dependencies = [ + "darling 0.20.11", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "mach2" version = "0.4.3" @@ -901,6 +1958,12 @@ dependencies = [ "thread-tree", ] +[[package]] +name = "md5" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae960838283323069879657ca3de837e9f7bbb4c7bf6ea7f1b290d5e9476d2e0" + [[package]] name = "memchr" version = "2.8.0" @@ -917,6 +1980,38 @@ dependencies = [ "simd-adler32", ] +[[package]] +name = "moddef" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a0b3262dc837d2513fe2ef31ff8461352ef932dcca31ba0c0abe33547cf6b9b" + +[[package]] +name = "naga" +version = "29.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2630921705b9b01dcdd0b6864b9562ca3c1951eecd0f0c4f5f04f61e412647" +dependencies = [ + "arrayvec", + "bit-set", + "bitflags 2.11.0", + "cfg-if", + "cfg_aliases", + "codespan-reporting", + "half", + "hashbrown 0.16.1", + "hexf-parse", + "indexmap", + "libm", + "log", + "num-traits", + "once_cell", + "rustc-hash 1.1.0", + "spirv", + "thiserror", + "unicode-ident", +] + [[package]] name = "native-tls" version = "0.2.18" @@ -934,6 +2029,21 @@ dependencies = [ "tempfile", ] +[[package]] +name = "nb" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" +dependencies = [ + "nb 1.1.0", +] + +[[package]] +name = "nb" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" + [[package]] name = "ndarray" version = "0.17.2" @@ -945,9 +2055,8 @@ dependencies = [ "cranelift-frontend", "cranelift-jit", "cranelift-module", - "critical-section", + "criterion", "defmac", - "fractal", "itertools 0.13.0", "libc", "matrixmultiply", @@ -956,6 +2065,7 @@ dependencies = [ "num-integer", "num-traits", "p64", + "phyllotactic-manifold", "portable-atomic", "portable-atomic-util", "quickcheck", @@ -977,13 +2087,23 @@ dependencies = [ name = "ndarray-rand" version = "0.16.0" dependencies = [ + "criterion", "ndarray", "quickcheck", "rand 0.9.2", - "rand_distr", + "rand_distr 0.5.1", "rand_isaac", ] +[[package]] +name = "ndk-sys" +version = "0.6.0+11769913" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" +dependencies = [ + "jni-sys 0.3.1", +] + [[package]] name = "netlib-src" version = "0.8.0" @@ -993,6 +2113,39 @@ dependencies = [ "cmake", ] +[[package]] +name = "nom" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +dependencies = [ + "memchr", +] + +[[package]] +name = "num" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + [[package]] name = "num-complex" version = "0.4.6" @@ -1011,6 +2164,28 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -1043,7 +2218,78 @@ dependencies = [ "num-traits", "openblas-src", "rand 0.9.2", - "rand_distr", + "rand_distr 0.5.1", +] + +[[package]] +name = "objc2" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" +dependencies = [ + "objc2-encode", +] + +[[package]] +name = "objc2-core-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" +dependencies = [ + "bitflags 2.11.0", + "dispatch2", + "objc2", +] + +[[package]] +name = "objc2-encode" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" + +[[package]] +name = "objc2-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" +dependencies = [ + "bitflags 2.11.0", + "objc2", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-metal" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0125f776a10d00af4152d74616409f0d4a2053a6f57fa5b7d6aa2854ac04794" +dependencies = [ + "bitflags 2.11.0", + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" +dependencies = [ + "bitflags 2.11.0", + "objc2", + "objc2-core-foundation", + "objc2-foundation", + "objc2-metal", +] + +[[package]] +name = "object" +version = "0.37.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" +dependencies = [ + "memchr", ] [[package]] @@ -1052,6 +2298,12 @@ version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" +[[package]] +name = "oneshot" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfe21416a02c693fb9f980befcb230ecc70b0b3d1cc4abf88b9675c4c1457f0c" + [[package]] name = "oorandom" version = "11.1.5" @@ -1134,12 +2386,50 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" +[[package]] +name = "ordered-float" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7d950ca161dc355eaf28f82b11345ed76c6e1f6eb1f4f4479e0323b9e2fbd0e" +dependencies = [ + "num-traits", +] + [[package]] name = "p64" version = "0.1.0" dependencies = [ "criterion", - "fractal", + "phyllotactic-manifold", +] + +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.5.18", + "smallvec", + "windows-link", ] [[package]] @@ -1163,6 +2453,31 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" +[[package]] +name = "petgraph" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455" +dependencies = [ + "fixedbitset", + "hashbrown 0.15.5", + "indexmap", + "serde", +] + +[[package]] +name = "phyllotactic-manifold" +version = "0.1.0" +dependencies = [ + "criterion", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + [[package]] name = "pkg-config" version = "0.3.32" @@ -1210,6 +2525,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" dependencies = [ "critical-section", + "serde", ] [[package]] @@ -1230,6 +2546,12 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "presser" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa" + [[package]] name = "prettyplease" version = "0.2.37" @@ -1249,6 +2571,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "profiling" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eb8486b569e12e2c32ad3e204dbaba5e4b5b216e9367044f25f1dba42341773" + [[package]] name = "quickcheck" version = "1.1.0" @@ -1295,6 +2623,7 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc266eb313df6c5c09c1c7b1fbe2510961e5bcd3add930c1e31f7ed9da0feff8" dependencies = [ + "chacha20", "getrandom 0.4.2", "rand_core 0.10.0", ] @@ -1334,6 +2663,16 @@ dependencies = [ "rand 0.9.2", ] +[[package]] +name = "rand_distr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d431c2703ccf129de4d45253c03f49ebb22b97d6ad79ee3ecfc7e3f4862c1d8" +dependencies = [ + "num-traits", + "rand 0.10.0", +] + [[package]] name = "rand_isaac" version = "0.4.0" @@ -1343,6 +2682,30 @@ dependencies = [ "rand_core 0.9.5", ] +[[package]] +name = "range-alloc" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca45419789ae5a7899559e9512e58ca889e41f04f1f2445e9f4b290ceccd1d08" + +[[package]] +name = "raw-window-handle" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" + +[[package]] +name = "raw-window-metal" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40d213455a5f1dc59214213c7330e074ddf8114c9a42411eb890c767357ce135" +dependencies = [ + "objc2", + "objc2-core-foundation", + "objc2-foundation", + "objc2-quartz-core", +] + [[package]] name = "rawpointer" version = "0.2.1" @@ -1369,6 +2732,15 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags 2.11.0", +] + [[package]] name = "redox_syscall" version = "0.7.3" @@ -1399,7 +2771,7 @@ dependencies = [ "bumpalo", "hashbrown 0.15.5", "log", - "rustc-hash", + "rustc-hash 2.1.2", "smallvec", ] @@ -1444,6 +2816,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "renderdoc-sys" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" + [[package]] name = "rmp" version = "0.8.13" @@ -1478,12 +2856,33 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "rustc-demangle" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustc-hash" version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + [[package]] name = "rustix" version = "1.1.4" @@ -1521,6 +2920,15 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "sanitize-filename" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc984f4f9ceb736a7bb755c3e3bd17dc56370af2600c9780dcc48c66453da34d" +dependencies = [ + "regex", +] + [[package]] name = "schannel" version = "0.1.29" @@ -1530,6 +2938,12 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + [[package]] name = "security-framework" version = "3.7.0" @@ -1559,6 +2973,12 @@ version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" +[[package]] +name = "seq-macro" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc711410fbe7399f390ca1c3b60ad0f53f80e95c5eb935e52268a0e2cd49acc" + [[package]] name = "serde" version = "1.0.228" @@ -1569,6 +2989,16 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde_bytes" +version = "0.11.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5d440709e79d88e51ac01c4b72fc6cb7314017bb7da9eeff678aa94c10e3ea8" +dependencies = [ + "serde", + "serde_core", +] + [[package]] name = "serde_core" version = "1.0.228" @@ -1602,6 +3032,15 @@ dependencies = [ "zmij", ] +[[package]] +name = "serde_spanned" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "876ac351060d4f882bb1032b6369eb0aef79ad9df1ea8bc404874d8cc3d0cd98" +dependencies = [ + "serde_core", +] + [[package]] name = "serialization-tests" version = "0.1.0" @@ -1626,17 +3065,72 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "slotmap" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdd58c3c93c3d278ca835519292445cb4b0d4dc59ccfdf7ceadaab3f8aeb4038" +dependencies = [ + "version_check", +] + [[package]] name = "smallvec" version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +dependencies = [ + "serde", +] + +[[package]] +name = "spin" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5fe4ccb98d9c292d56fec89a5e07da7fc4cf0dc11e156b41793132775d3e591" +dependencies = [ + "lock_api", + "portable-atomic", +] + +[[package]] +name = "spirv" +version = "0.4.0+sdk-1.4.341.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9571ea910ebd84c86af4b3ed27f9dbdc6ad06f17c5f96146b2b671e2976744f" +dependencies = [ + "bitflags 2.11.0", +] + +[[package]] +name = "stable-vec" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dac7bc0f7d0d44329b200020effbc25a534d89fa142af95e3ddf76113412a5e" + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] -name = "stable_deref_trait" -version = "1.2.1" +name = "strsim" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" @@ -1679,6 +3173,15 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + [[package]] name = "thiserror" version = "2.0.18" @@ -1708,6 +3211,15 @@ dependencies = [ "crossbeam-channel", ] +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + [[package]] name = "tinytemplate" version = "1.2.1" @@ -1718,18 +3230,93 @@ dependencies = [ "serde_json", ] +[[package]] +name = "toml" +version = "1.1.0+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8195ca05e4eb728f4ba94f3e3291661320af739c4e43779cbdfae82ab239fcc" +dependencies = [ + "indexmap", + "serde_core", + "serde_spanned", + "toml_datetime", + "toml_parser", + "toml_writer", + "winnow", +] + +[[package]] +name = "toml_datetime" +version = "1.1.0+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97251a7c317e03ad83774a8752a7e81fb6067740609f75ea2b585b569a59198f" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_parser" +version = "1.1.0+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2334f11ee363607eb04df9b8fc8a13ca1715a72ba8662a26ac285c98aabb4011" +dependencies = [ + "winnow", +] + +[[package]] +name = "toml_writer" +version = "1.1.0+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d282ade6016312faf3e41e57ebbba0c073e4056dab1232ab1cb624199648f8ed" + +[[package]] +name = "tynm" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21cdb0fc8f85c98b1ec812bc4cd69faf6c0fa2fc17d44ea3c2cdd38dc08e999" +dependencies = [ + "nom", +] + +[[package]] +name = "type-map" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb30dbbd9036155e74adad6812e9898d03ec374946234fbcebd5dfc7b9187b90" +dependencies = [ + "rustc-hash 2.1.2", +] + [[package]] name = "unicode-ident" version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +[[package]] +name = "unicode-segmentation" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" + +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + [[package]] name = "unicode-xid" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" +[[package]] +name = "unty" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d49784317cd0d1ee7ec5c716dd598ec5b4483ea832a2dced265471cc0f690ae" + [[package]] name = "ureq" version = "3.3.0" @@ -1765,12 +3352,35 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8c0a043c9540bae7c578c88f91dda8bd82e59ae27c21baca69c8b191aaf5a6e" +[[package]] +name = "variadics_please" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41b6d82be61465f97d42bd1d15bf20f3b0a3a0905018f38f9d6f6962055b0b5c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "vcpkg" version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + [[package]] name = "walkdir" version = "2.5.0" @@ -1818,6 +3428,16 @@ dependencies = [ "wasm-bindgen-shared", ] +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d1faf851e778dfa54db7cd438b70758eba9755cb47403f3496edd7c8fc212f0" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "wasm-bindgen-macro" version = "0.2.115" @@ -1896,6 +3516,18 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "wayland-sys" +version = "0.31.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "374f6b70e8e0d6bf9461a32988fd553b59ff630964924dad6e4a4eb6bd538d17" +dependencies = [ + "dlib", + "log", + "once_cell", + "pkg-config", +] + [[package]] name = "web-sys" version = "0.3.92" @@ -1906,6 +3538,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "webpki-root-certs" version = "1.0.6" @@ -1915,6 +3557,173 @@ dependencies = [ "rustls-pki-types", ] +[[package]] +name = "wgpu" +version = "29.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72c239a9a747bbd379590985bac952c2e53cb19873f7072b3370c6a6a8e06837" +dependencies = [ + "arrayvec", + "bitflags 2.11.0", + "bytemuck", + "cfg-if", + "cfg_aliases", + "document-features", + "hashbrown 0.16.1", + "js-sys", + "log", + "naga", + "parking_lot", + "portable-atomic", + "profiling", + "raw-window-handle", + "smallvec", + "static_assertions", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "wgpu-core", + "wgpu-hal", + "wgpu-types", +] + +[[package]] +name = "wgpu-core" +version = "29.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e80ac6cf1895df6342f87d975162108f9d98772a0d74bc404ab7304ac29469e" +dependencies = [ + "arrayvec", + "bit-set", + "bit-vec", + "bitflags 2.11.0", + "bytemuck", + "cfg_aliases", + "document-features", + "hashbrown 0.16.1", + "indexmap", + "log", + "naga", + "once_cell", + "parking_lot", + "portable-atomic", + "profiling", + "raw-window-handle", + "rustc-hash 1.1.0", + "smallvec", + "thiserror", + "wgpu-core-deps-apple", + "wgpu-core-deps-emscripten", + "wgpu-core-deps-windows-linux-android", + "wgpu-hal", + "wgpu-naga-bridge", + "wgpu-types", +] + +[[package]] +name = "wgpu-core-deps-apple" +version = "29.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43acd053312501689cd92a01a9638d37f3e41a5fd9534875efa8917ee2d11ac0" +dependencies = [ + "wgpu-hal", +] + +[[package]] +name = "wgpu-core-deps-emscripten" +version = "29.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef043bf135cc68b6f667c55ff4e345ce2b5924d75bad36a47921b0287ca4b24a" +dependencies = [ + "wgpu-hal", +] + +[[package]] +name = "wgpu-core-deps-windows-linux-android" +version = "29.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "725d5c006a8c02967b6d93ef04f6537ec4593313e330cfe86d9d3f946eb90f28" +dependencies = [ + "wgpu-hal", +] + +[[package]] +name = "wgpu-hal" +version = "29.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89a47aef47636562f3937285af4c44b4b5b404b46577471411cc5313a921da7e" +dependencies = [ + "android_system_properties", + "arrayvec", + "ash", + "bit-set", + "bitflags 2.11.0", + "block2", + "bytemuck", + "cfg-if", + "cfg_aliases", + "glow", + "glutin_wgl_sys", + "gpu-allocator", + "gpu-descriptor", + "hashbrown 0.16.1", + "js-sys", + "khronos-egl", + "libc", + "libloading 0.8.9", + "log", + "naga", + "ndk-sys", + "objc2", + "objc2-core-foundation", + "objc2-foundation", + "objc2-metal", + "objc2-quartz-core", + "once_cell", + "ordered-float", + "parking_lot", + "portable-atomic", + "portable-atomic-util", + "profiling", + "range-alloc", + "raw-window-handle", + "raw-window-metal", + "renderdoc-sys", + "smallvec", + "thiserror", + "wasm-bindgen", + "wayland-sys", + "web-sys", + "wgpu-naga-bridge", + "wgpu-types", + "windows", + "windows-core", +] + +[[package]] +name = "wgpu-naga-bridge" +version = "29.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b4684f4410da0cf95a4cb63bb5edaac022461dedb6adf0b64d0d9b5f6890d51" +dependencies = [ + "naga", + "wgpu-types", +] + +[[package]] +name = "wgpu-types" +version = "29.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec2675540fb1a5cfa5ef122d3d5f390e2c75711a0b946410f2d6ac3a0f77d1f6" +dependencies = [ + "bitflags 2.11.0", + "bytemuck", + "js-sys", + "log", + "raw-window-handle", + "web-sys", +] + [[package]] name = "winapi-util" version = "0.1.11" @@ -1924,12 +3733,107 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "windows" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580" +dependencies = [ + "windows-collections", + "windows-core", + "windows-future", + "windows-numerics", +] + +[[package]] +name = "windows-collections" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610" +dependencies = [ + "windows-core", +] + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-future" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb" +dependencies = [ + "windows-core", + "windows-link", + "windows-threading", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "windows-link" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" +[[package]] +name = "windows-numerics" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26" +dependencies = [ + "windows-core", + "windows-link", +] + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", +] + [[package]] name = "windows-sys" version = "0.52.0" @@ -1973,6 +3877,15 @@ dependencies = [ "windows_x86_64_msvc", ] +[[package]] +name = "windows-threading" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37" +dependencies = [ + "windows-link", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" @@ -2021,6 +3934,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "winnow" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09dac053f1cd375980747450bfc7250c264eaae0583872e845c0c7cd578872b5" + [[package]] name = "wit-bindgen" version = "0.51.0" @@ -2119,6 +4038,18 @@ dependencies = [ "rustix", ] +[[package]] +name = "xml-rs" +version = "0.8.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f" + +[[package]] +name = "xxhash-rust" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdd20c5420375476fbd4394763288da7eb0cc0b8c11deed431a91562af7335d3" + [[package]] name = "zerocopy" version = "0.8.48" diff --git a/Cargo.toml b/Cargo.toml index ea01bc3f..43ca7658 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -79,6 +79,56 @@ quickcheck = { workspace = true } approx = { workspace = true, default-features = true } itertools = { workspace = true } ndarray-gen = { workspace = true } +criterion = { version = "0.5", features = ["html_reports"] } + +[[bench]] +name = "append" +harness = false + +[[bench]] +name = "bench1" +harness = false + +[[bench]] +name = "chunks" +harness = false + +[[bench]] +name = "construct" +harness = false + +[[bench]] +name = "gemv_gemm" +harness = false + +[[bench]] +name = "higher-order" +harness = false + +[[bench]] +name = "iter" +harness = false + +[[bench]] +name = "numeric" +harness = false + +[[bench]] +name = "par_rayon" +harness = false +required-features = ["rayon"] + +[[bench]] +name = "reserve" +harness = false + +[[bench]] +name = "to_shape" +harness = false + +[[bench]] +name = "zip" +harness = false [features] default = ["std", "hpc-extras"] diff --git a/benches/append.rs b/benches/append.rs index b9ca99c6..aecb60cf 100644 --- a/benches/append.rs +++ b/benches/append.rs @@ -1,29 +1,30 @@ -#![feature(test)] - -extern crate test; -use test::Bencher; - +use criterion::{black_box, criterion_group, criterion_main, Criterion}; use ndarray::prelude::*; -#[bench] -fn select_axis0(bench: &mut Bencher) { +fn select_axis0(c: &mut Criterion) { let a = Array::::zeros((256, 256)); let selectable = vec![0, 1, 2, 0, 1, 3, 0, 4, 16, 32, 128, 147, 149, 220, 221, 255, 221, 0, 1]; - bench.iter(|| a.select(Axis(0), &selectable)); + c.bench_function("select_axis0", |b| { + b.iter(|| black_box(&a).select(Axis(0), black_box(&selectable))) + }); } -#[bench] -fn select_axis1(bench: &mut Bencher) { +fn select_axis1(c: &mut Criterion) { let a = Array::::zeros((256, 256)); let selectable = vec![0, 1, 2, 0, 1, 3, 0, 4, 16, 32, 128, 147, 149, 220, 221, 255, 221, 0, 1]; - bench.iter(|| a.select(Axis(1), &selectable)); + c.bench_function("select_axis1", |b| { + b.iter(|| black_box(&a).select(Axis(1), black_box(&selectable))) + }); } -#[bench] -fn select_1d(bench: &mut Bencher) { +fn select_1d(c: &mut Criterion) { let a = Array::::zeros(1024); let mut selectable = (0..a.len()).step_by(17).collect::>(); selectable.extend(selectable.clone().iter().rev()); - - bench.iter(|| a.select(Axis(0), &selectable)); + c.bench_function("select_1d", |b| { + b.iter(|| black_box(&a).select(Axis(0), black_box(&selectable))) + }); } + +criterion_group!(benches, select_axis0, select_axis1, select_1d); +criterion_main!(benches); diff --git a/benches/bench1.rs b/benches/bench1.rs index e534c04d..e06676d5 100644 --- a/benches/bench1.rs +++ b/benches/bench1.rs @@ -1,741 +1,845 @@ -#![feature(test)] +// `s![1..-1, 1..-1]` — ndarray's `s!` macro uses Python-style negative +// indexing. Clippy can't see through the macro and reads `1..-1` as a +// plain (empty) Rust range; the actual semantics are correct. #![allow(unused_imports)] -#![allow(clippy::many_single_char_names, clippy::deref_addrof, clippy::unreadable_literal)] - -extern crate test; +#![allow(clippy::many_single_char_names, clippy::deref_addrof, clippy::unreadable_literal, clippy::reversed_empty_ranges)] use std::mem::MaybeUninit; +use criterion::{black_box, criterion_group, criterion_main, Criterion}; use ndarray::{arr0, arr1, arr2, azip, s}; use ndarray::{Array, Array1, Array2, Axis, Ix, Zip}; use ndarray::{Array3, Array4, ShapeBuilder}; use ndarray::{Ix1, Ix2, Ix3, Ix5, IxDyn}; -use test::black_box; - -#[bench] -fn iter_sum_1d_regular(bench: &mut test::Bencher) { +fn iter_sum_1d_regular(c: &mut Criterion) +{ let a = Array::::zeros(64 * 64); let a = black_box(a); - bench.iter(|| { - let mut sum = 0; - for &elt in a.iter() { - sum += elt; - } - sum + c.bench_function("iter_sum_1d_regular", |bn| { + bn.iter(|| { + let mut sum = 0; + for &elt in a.iter() { + sum += elt; + } + sum + }) }); } -#[bench] -fn iter_sum_1d_raw(bench: &mut test::Bencher) { - // this is autovectorized to death (= great performance) +fn iter_sum_1d_raw(c: &mut Criterion) +{ let a = Array::::zeros(64 * 64); let a = black_box(a); - bench.iter(|| { - let mut sum = 0; - for &elt in a.as_slice_memory_order().unwrap() { - sum += elt; - } - sum + c.bench_function("iter_sum_1d_raw", |bn| { + bn.iter(|| { + let mut sum = 0; + for &elt in a.as_slice_memory_order().unwrap() { + sum += elt; + } + sum + }) }); } -#[bench] -fn iter_sum_2d_regular(bench: &mut test::Bencher) { +fn iter_sum_2d_regular(c: &mut Criterion) +{ let a = Array::::zeros((64, 64)); let a = black_box(a); - bench.iter(|| { - let mut sum = 0; - for &elt in a.iter() { - sum += elt; - } - sum + c.bench_function("iter_sum_2d_regular", |bn| { + bn.iter(|| { + let mut sum = 0; + for &elt in a.iter() { + sum += elt; + } + sum + }) }); } -#[bench] -fn iter_sum_2d_by_row(bench: &mut test::Bencher) { +fn iter_sum_2d_by_row(c: &mut Criterion) +{ let a = Array::::zeros((64, 64)); let a = black_box(a); - bench.iter(|| { - let mut sum = 0; - for row in a.rows() { - for &elt in row { - sum += elt; + c.bench_function("iter_sum_2d_by_row", |bn| { + bn.iter(|| { + let mut sum = 0; + for row in a.rows() { + for &elt in row { + sum += elt; + } } - } - sum + sum + }) }); } -#[bench] -fn iter_sum_2d_raw(bench: &mut test::Bencher) { - // this is autovectorized to death (= great performance) +fn iter_sum_2d_raw(c: &mut Criterion) +{ let a = Array::::zeros((64, 64)); let a = black_box(a); - bench.iter(|| { - let mut sum = 0; - for &elt in a.as_slice_memory_order().unwrap() { - sum += elt; - } - sum + c.bench_function("iter_sum_2d_raw", |bn| { + bn.iter(|| { + let mut sum = 0; + for &elt in a.as_slice_memory_order().unwrap() { + sum += elt; + } + sum + }) }); } -#[bench] -fn iter_sum_2d_cutout(bench: &mut test::Bencher) { +fn iter_sum_2d_cutout(c: &mut Criterion) +{ let a = Array::::zeros((66, 66)); let av = a.slice(s![1..-1, 1..-1]); let a = black_box(av); - bench.iter(|| { - let mut sum = 0; - for &elt in a.iter() { - sum += elt; - } - sum + c.bench_function("iter_sum_2d_cutout", |bn| { + bn.iter(|| { + let mut sum = 0; + for &elt in a.iter() { + sum += elt; + } + sum + }) }); } -#[bench] -fn iter_sum_2d_cutout_by_row(bench: &mut test::Bencher) { +fn iter_sum_2d_cutout_by_row(c: &mut Criterion) +{ let a = Array::::zeros((66, 66)); let av = a.slice(s![1..-1, 1..-1]); let a = black_box(av); - bench.iter(|| { - let mut sum = 0; - for row in 0..a.shape()[0] { - for &elt in a.row(row) { - sum += elt; + c.bench_function("iter_sum_2d_cutout_by_row", |bn| { + bn.iter(|| { + let mut sum = 0; + for row in 0..a.shape()[0] { + for &elt in a.row(row) { + sum += elt; + } } - } - sum + sum + }) }); } -#[bench] -fn iter_sum_2d_cutout_outer_iter(bench: &mut test::Bencher) { +fn iter_sum_2d_cutout_outer_iter(c: &mut Criterion) +{ let a = Array::::zeros((66, 66)); let av = a.slice(s![1..-1, 1..-1]); let a = black_box(av); - bench.iter(|| { - let mut sum = 0; - for row in a.rows() { - for &elt in row { - sum += elt; + c.bench_function("iter_sum_2d_cutout_outer_iter", |bn| { + bn.iter(|| { + let mut sum = 0; + for row in a.rows() { + for &elt in row { + sum += elt; + } } - } - sum + sum + }) }); } -#[bench] -fn iter_sum_2d_transpose_regular(bench: &mut test::Bencher) { +fn iter_sum_2d_transpose_regular(c: &mut Criterion) +{ let mut a = Array::::zeros((64, 64)); a.swap_axes(0, 1); let a = black_box(a); - bench.iter(|| { - let mut sum = 0; - for &elt in a.iter() { - sum += elt; - } - sum + c.bench_function("iter_sum_2d_transpose_regular", |bn| { + bn.iter(|| { + let mut sum = 0; + for &elt in a.iter() { + sum += elt; + } + sum + }) }); } -#[bench] -fn iter_sum_2d_transpose_by_row(bench: &mut test::Bencher) { +fn iter_sum_2d_transpose_by_row(c: &mut Criterion) +{ let mut a = Array::::zeros((64, 64)); a.swap_axes(0, 1); let a = black_box(a); - bench.iter(|| { - let mut sum = 0; - for row in 0..a.shape()[0] { - for &elt in a.row(row) { - sum += elt; + c.bench_function("iter_sum_2d_transpose_by_row", |bn| { + bn.iter(|| { + let mut sum = 0; + for row in 0..a.shape()[0] { + for &elt in a.row(row) { + sum += elt; + } } - } - sum + sum + }) }); } -#[bench] -fn sum_2d_regular(bench: &mut test::Bencher) { +fn sum_2d_regular(c: &mut Criterion) +{ let a = Array::::zeros((64, 64)); let a = black_box(a); - bench.iter(|| a.sum()); + c.bench_function("sum_2d_regular", |bn| bn.iter(|| a.sum())); } -#[bench] -fn sum_2d_cutout(bench: &mut test::Bencher) { +fn sum_2d_cutout(c: &mut Criterion) +{ let a = Array::::zeros((66, 66)); let av = a.slice(s![1..-1, 1..-1]); let a = black_box(av); - bench.iter(|| a.sum()); + c.bench_function("sum_2d_cutout", |bn| bn.iter(|| a.sum())); } -#[bench] -fn sum_2d_float(bench: &mut test::Bencher) { +fn sum_2d_float(c: &mut Criterion) +{ let a = Array::::zeros((64, 64)); let a = black_box(a.view()); - bench.iter(|| a.sum()); + c.bench_function("sum_2d_float", |bn| bn.iter(|| a.sum())); } -#[bench] -fn sum_2d_float_cutout(bench: &mut test::Bencher) { +fn sum_2d_float_cutout(c: &mut Criterion) +{ let a = Array::::zeros((66, 66)); let av = a.slice(s![1..-1, 1..-1]); let a = black_box(av); - bench.iter(|| a.sum()); + c.bench_function("sum_2d_float_cutout", |bn| bn.iter(|| a.sum())); } -#[bench] -fn sum_2d_float_t_cutout(bench: &mut test::Bencher) { +fn sum_2d_float_t_cutout(c: &mut Criterion) +{ let a = Array::::zeros((66, 66)); let av = a.slice(s![1..-1, 1..-1]).reversed_axes(); let a = black_box(av); - bench.iter(|| a.sum()); + c.bench_function("sum_2d_float_t_cutout", |bn| bn.iter(|| a.sum())); } -#[bench] -fn fold_sum_i32_2d_regular(bench: &mut test::Bencher) { +fn fold_sum_i32_2d_regular(c: &mut Criterion) +{ let a = Array::::zeros((64, 64)); - bench.iter(|| a.fold(0, |acc, &x| acc + x)); + c.bench_function("fold_sum_i32_2d_regular", |bn| { + bn.iter(|| a.fold(0, |acc, &x| acc + x)) + }); } -#[bench] -fn fold_sum_i32_2d_cutout(bench: &mut test::Bencher) { +fn fold_sum_i32_2d_cutout(c: &mut Criterion) +{ let a = Array::::zeros((66, 66)); let av = a.slice(s![1..-1, 1..-1]); let a = black_box(av); - bench.iter(|| a.fold(0, |acc, &x| acc + x)); + c.bench_function("fold_sum_i32_2d_cutout", |bn| { + bn.iter(|| a.fold(0, |acc, &x| acc + x)) + }); } -#[bench] -fn fold_sum_i32_2d_stride(bench: &mut test::Bencher) { +fn fold_sum_i32_2d_stride(c: &mut Criterion) +{ let a = Array::::zeros((64, 128)); let av = a.slice(s![.., ..;2]); let a = black_box(av); - bench.iter(|| a.fold(0, |acc, &x| acc + x)); + c.bench_function("fold_sum_i32_2d_stride", |bn| { + bn.iter(|| a.fold(0, |acc, &x| acc + x)) + }); } -#[bench] -fn fold_sum_i32_2d_transpose(bench: &mut test::Bencher) { +fn fold_sum_i32_2d_transpose(c: &mut Criterion) +{ let a = Array::::zeros((64, 64)); let a = a.t(); - bench.iter(|| a.fold(0, |acc, &x| acc + x)); + c.bench_function("fold_sum_i32_2d_transpose", |bn| { + bn.iter(|| a.fold(0, |acc, &x| acc + x)) + }); } -#[bench] -fn fold_sum_i32_2d_cutout_transpose(bench: &mut test::Bencher) { +fn fold_sum_i32_2d_cutout_transpose(c: &mut Criterion) +{ let a = Array::::zeros((66, 66)); let mut av = a.slice(s![1..-1, 1..-1]); av.swap_axes(0, 1); let a = black_box(av); - bench.iter(|| a.fold(0, |acc, &x| acc + x)); + c.bench_function("fold_sum_i32_2d_cutout_transpose", |bn| { + bn.iter(|| a.fold(0, |acc, &x| acc + x)) + }); } const ADD2DSZ: usize = 64; -#[bench] -fn add_2d_regular(bench: &mut test::Bencher) { +fn add_2d_regular(c: &mut Criterion) +{ let mut a = Array::::zeros((ADD2DSZ, ADD2DSZ)); let b = Array::::zeros((ADD2DSZ, ADD2DSZ)); let bv = b.view(); - bench.iter(|| { - a += &bv; + c.bench_function("add_2d_regular", |bn| { + bn.iter(|| { + a += &bv; + }) }); } -#[bench] -fn add_2d_zip(bench: &mut test::Bencher) { +fn add_2d_zip(c: &mut Criterion) +{ let mut a = Array::::zeros((ADD2DSZ, ADD2DSZ)); let b = Array::::zeros((ADD2DSZ, ADD2DSZ)); - bench.iter(|| { - Zip::from(&mut a).and(&b).for_each(|a, &b| *a += b); + c.bench_function("add_2d_zip", |bn| { + bn.iter(|| { + Zip::from(&mut a).and(&b).for_each(|a, &b| *a += b); + }) }); } -#[bench] -fn add_2d_alloc_plus(bench: &mut test::Bencher) { +fn add_2d_alloc_plus(c: &mut Criterion) +{ let a = Array::::zeros((ADD2DSZ, ADD2DSZ)); let b = Array::::zeros((ADD2DSZ, ADD2DSZ)); - bench.iter(|| &a + &b); + c.bench_function("add_2d_alloc_plus", |bn| bn.iter(|| &a + &b)); } -#[bench] -fn add_2d_alloc_zip_uninit(bench: &mut test::Bencher) { +fn add_2d_alloc_zip_uninit(c: &mut Criterion) +{ let a = Array::::zeros((ADD2DSZ, ADD2DSZ)); let b = Array::::zeros((ADD2DSZ, ADD2DSZ)); - bench.iter(|| unsafe { - let mut c = Array::::uninit(a.dim()); - azip!((&a in &a, &b in &b, c in c.raw_view_mut().cast::()) - c.write(a + b) - ); - c + c.bench_function("add_2d_alloc_zip_uninit", |bn| { + bn.iter(|| unsafe { + let mut c_arr = Array::::uninit(a.dim()); + azip!((&a in &a, &b in &b, c in c_arr.raw_view_mut().cast::()) + c.write(a + b) + ); + c_arr + }) }); } -#[bench] -fn add_2d_alloc_zip_collect(bench: &mut test::Bencher) { +fn add_2d_alloc_zip_collect(c: &mut Criterion) +{ let a = Array::::zeros((ADD2DSZ, ADD2DSZ)); let b = Array::::zeros((ADD2DSZ, ADD2DSZ)); - bench.iter(|| Zip::from(&a).and(&b).map_collect(|&x, &y| x + y)); + c.bench_function("add_2d_alloc_zip_collect", |bn| { + bn.iter(|| Zip::from(&a).and(&b).map_collect(|&x, &y| x + y)) + }); } -#[bench] -fn vec_string_collect(bench: &mut test::Bencher) { +fn vec_string_collect(c: &mut Criterion) +{ let v = vec![""; 10240]; - bench.iter(|| v.iter().map(|s| s.to_owned()).collect::>()); + c.bench_function("vec_string_collect", |bn| { + bn.iter(|| v.iter().map(|s| s.to_owned()).collect::>()) + }); } -#[bench] -fn array_string_collect(bench: &mut test::Bencher) { +fn array_string_collect(c: &mut Criterion) +{ let v = Array::from(vec![""; 10240]); - bench.iter(|| Zip::from(&v).map_collect(|s| s.to_owned())); + c.bench_function("array_string_collect", |bn| { + bn.iter(|| Zip::from(&v).map_collect(|s| s.to_owned())) + }); } -#[bench] -fn vec_f64_collect(bench: &mut test::Bencher) { +fn vec_f64_collect(c: &mut Criterion) +{ let v = vec![1.; 10240]; - bench.iter(|| v.iter().map(|s| s + 1.).collect::>()); + c.bench_function("vec_f64_collect", |bn| { + bn.iter(|| v.iter().map(|s| s + 1.).collect::>()) + }); } -#[bench] -fn array_f64_collect(bench: &mut test::Bencher) { +fn array_f64_collect(c: &mut Criterion) +{ let v = Array::from(vec![1.; 10240]); - bench.iter(|| Zip::from(&v).map_collect(|s| s + 1.)); + c.bench_function("array_f64_collect", |bn| { + bn.iter(|| Zip::from(&v).map_collect(|s| s + 1.)) + }); } -#[bench] -fn add_2d_assign_ops(bench: &mut test::Bencher) { +fn add_2d_assign_ops(c: &mut Criterion) +{ let mut a = Array::::zeros((ADD2DSZ, ADD2DSZ)); let b = Array::::zeros((ADD2DSZ, ADD2DSZ)); let bv = b.view(); - bench.iter(|| { - let mut x = a.view_mut(); - x += &bv; - black_box(x); + c.bench_function("add_2d_assign_ops", |bn| { + bn.iter(|| { + let mut x = a.view_mut(); + x += &bv; + black_box(x); + }) }); } -#[bench] -fn add_2d_cutout(bench: &mut test::Bencher) { +fn add_2d_cutout(c: &mut Criterion) +{ let mut a = Array::::zeros((ADD2DSZ + 2, ADD2DSZ + 2)); let mut acut = a.slice_mut(s![1..-1, 1..-1]); let b = Array::::zeros((ADD2DSZ, ADD2DSZ)); let bv = b.view(); - bench.iter(|| { - acut += &bv; + c.bench_function("add_2d_cutout", |bn| { + bn.iter(|| { + acut += &bv; + }) }); } -#[bench] -fn add_2d_zip_cutout(bench: &mut test::Bencher) { +fn add_2d_zip_cutout(c: &mut Criterion) +{ let mut a = Array::::zeros((ADD2DSZ + 2, ADD2DSZ + 2)); let mut acut = a.slice_mut(s![1..-1, 1..-1]); let b = Array::::zeros((ADD2DSZ, ADD2DSZ)); - bench.iter(|| { - Zip::from(&mut acut).and(&b).for_each(|a, &b| *a += b); + c.bench_function("add_2d_zip_cutout", |bn| { + bn.iter(|| { + Zip::from(&mut acut).and(&b).for_each(|a, &b| *a += b); + }) }); } -#[bench] #[allow(clippy::identity_op)] -fn add_2d_cutouts_by_4(bench: &mut test::Bencher) { +fn add_2d_cutouts_by_4(c: &mut Criterion) +{ let mut a = Array::::zeros((64 * 1, 64 * 1)); let b = Array::::zeros((64 * 1, 64 * 1)); let chunksz = (4, 4); - bench.iter(|| { - Zip::from(a.exact_chunks_mut(chunksz)) - .and(b.exact_chunks(chunksz)) - .for_each(|mut a, b| a += &b); + c.bench_function("add_2d_cutouts_by_4", |bn| { + bn.iter(|| { + Zip::from(a.exact_chunks_mut(chunksz)) + .and(b.exact_chunks(chunksz)) + .for_each(|mut a, b| a += &b); + }) }); } -#[bench] #[allow(clippy::identity_op)] -fn add_2d_cutouts_by_16(bench: &mut test::Bencher) { +fn add_2d_cutouts_by_16(c: &mut Criterion) +{ let mut a = Array::::zeros((64 * 1, 64 * 1)); let b = Array::::zeros((64 * 1, 64 * 1)); let chunksz = (16, 16); - bench.iter(|| { - Zip::from(a.exact_chunks_mut(chunksz)) - .and(b.exact_chunks(chunksz)) - .for_each(|mut a, b| a += &b); + c.bench_function("add_2d_cutouts_by_16", |bn| { + bn.iter(|| { + Zip::from(a.exact_chunks_mut(chunksz)) + .and(b.exact_chunks(chunksz)) + .for_each(|mut a, b| a += &b); + }) }); } -#[bench] #[allow(clippy::identity_op)] -fn add_2d_cutouts_by_32(bench: &mut test::Bencher) { +fn add_2d_cutouts_by_32(c: &mut Criterion) +{ let mut a = Array::::zeros((64 * 1, 64 * 1)); let b = Array::::zeros((64 * 1, 64 * 1)); let chunksz = (32, 32); - bench.iter(|| { - Zip::from(a.exact_chunks_mut(chunksz)) - .and(b.exact_chunks(chunksz)) - .for_each(|mut a, b| a += &b); + c.bench_function("add_2d_cutouts_by_32", |bn| { + bn.iter(|| { + Zip::from(a.exact_chunks_mut(chunksz)) + .and(b.exact_chunks(chunksz)) + .for_each(|mut a, b| a += &b); + }) }); } -#[bench] -fn add_2d_broadcast_1_to_2(bench: &mut test::Bencher) { +fn add_2d_broadcast_1_to_2(c: &mut Criterion) +{ let mut a = Array2::::zeros((ADD2DSZ, ADD2DSZ)); let b = Array1::::zeros(ADD2DSZ); let bv = b.view(); - bench.iter(|| { - a += &bv; + c.bench_function("add_2d_broadcast_1_to_2", |bn| { + bn.iter(|| { + a += &bv; + }) }); } -#[bench] -fn add_2d_broadcast_0_to_2(bench: &mut test::Bencher) { +fn add_2d_broadcast_0_to_2(c: &mut Criterion) +{ let mut a = Array::::zeros((ADD2DSZ, ADD2DSZ)); let b = Array::::zeros(()); let bv = b.view(); - bench.iter(|| { - a += &bv; + c.bench_function("add_2d_broadcast_0_to_2", |bn| { + bn.iter(|| { + a += &bv; + }) }); } -#[bench] -fn scalar_toowned(bench: &mut test::Bencher) { +fn scalar_toowned(c: &mut Criterion) +{ let a = Array::::zeros((64, 64)); - bench.iter(|| a.to_owned()); + c.bench_function("scalar_toowned", |bn| bn.iter(|| a.to_owned())); } -#[bench] -fn scalar_add_1(bench: &mut test::Bencher) { +fn scalar_add_1(c: &mut Criterion) +{ let a = Array::::zeros((64, 64)); let n = 1.; - bench.iter(|| &a + n); + c.bench_function("scalar_add_1", |bn| bn.iter(|| &a + n)); } -#[bench] -fn scalar_add_2(bench: &mut test::Bencher) { +fn scalar_add_2(c: &mut Criterion) +{ let a = Array::::zeros((64, 64)); let n = 1.; - bench.iter(|| n + &a); + c.bench_function("scalar_add_2", |bn| bn.iter(|| n + &a)); } -#[bench] -fn scalar_add_strided_1(bench: &mut test::Bencher) { +fn scalar_add_strided_1(c: &mut Criterion) +{ let a = Array::from_shape_fn((64, 64 * 2), |(i, j)| (i * 64 + j) as f32).slice_move(s![.., ..;2]); let n = 1.; - bench.iter(|| &a + n); + c.bench_function("scalar_add_strided_1", |bn| bn.iter(|| &a + n)); } -#[bench] -fn scalar_add_strided_2(bench: &mut test::Bencher) { +fn scalar_add_strided_2(c: &mut Criterion) +{ let a = Array::from_shape_fn((64, 64 * 2), |(i, j)| (i * 64 + j) as f32).slice_move(s![.., ..;2]); let n = 1.; - bench.iter(|| n + &a); + c.bench_function("scalar_add_strided_2", |bn| bn.iter(|| n + &a)); } -#[bench] -fn scalar_sub_1(bench: &mut test::Bencher) { +fn scalar_sub_1(c: &mut Criterion) +{ let a = Array::::zeros((64, 64)); let n = 1.; - bench.iter(|| &a - n); + c.bench_function("scalar_sub_1", |bn| bn.iter(|| &a - n)); } -#[bench] -fn scalar_sub_2(bench: &mut test::Bencher) { +fn scalar_sub_2(c: &mut Criterion) +{ let a = Array::::zeros((64, 64)); let n = 1.; - bench.iter(|| n - &a); + c.bench_function("scalar_sub_2", |bn| bn.iter(|| n - &a)); } -// This is for comparison with add_2d_broadcast_0_to_2 -#[bench] -fn add_2d_0_to_2_iadd_scalar(bench: &mut test::Bencher) { +fn add_2d_0_to_2_iadd_scalar(c: &mut Criterion) +{ let mut a = Array::::zeros((ADD2DSZ, ADD2DSZ)); let n = black_box(0); - bench.iter(|| { - a += n; + c.bench_function("add_2d_0_to_2_iadd_scalar", |bn| { + bn.iter(|| { + a += n; + }) }); } -#[bench] -fn add_2d_strided(bench: &mut test::Bencher) { +fn add_2d_strided(c: &mut Criterion) +{ let mut a = Array::::zeros((ADD2DSZ, ADD2DSZ * 2)); let mut a = a.slice_mut(s![.., ..;2]); let b = Array::::zeros((ADD2DSZ, ADD2DSZ)); let bv = b.view(); - bench.iter(|| { - a += &bv; + c.bench_function("add_2d_strided", |bn| { + bn.iter(|| { + a += &bv; + }) }); } -#[bench] -fn add_2d_regular_dyn(bench: &mut test::Bencher) { +fn add_2d_regular_dyn(c: &mut Criterion) +{ let mut a = Array::::zeros(&[ADD2DSZ, ADD2DSZ][..]); let b = Array::::zeros(&[ADD2DSZ, ADD2DSZ][..]); let bv = b.view(); - bench.iter(|| { - a += &bv; + c.bench_function("add_2d_regular_dyn", |bn| { + bn.iter(|| { + a += &bv; + }) }); } -#[bench] -fn add_2d_strided_dyn(bench: &mut test::Bencher) { +fn add_2d_strided_dyn(c: &mut Criterion) +{ let mut a = Array::::zeros(&[ADD2DSZ, ADD2DSZ * 2][..]); let mut a = a.slice_mut(s![.., ..;2]); let b = Array::::zeros(&[ADD2DSZ, ADD2DSZ][..]); let bv = b.view(); - bench.iter(|| { - a += &bv; + c.bench_function("add_2d_strided_dyn", |bn| { + bn.iter(|| { + a += &bv; + }) }); } -#[bench] -fn add_2d_zip_strided(bench: &mut test::Bencher) { +fn add_2d_zip_strided(c: &mut Criterion) +{ let mut a = Array::::zeros((ADD2DSZ, ADD2DSZ * 2)); let mut a = a.slice_mut(s![.., ..;2]); let b = Array::::zeros((ADD2DSZ, ADD2DSZ)); - bench.iter(|| { - Zip::from(&mut a).and(&b).for_each(|a, &b| *a += b); + c.bench_function("add_2d_zip_strided", |bn| { + bn.iter(|| { + Zip::from(&mut a).and(&b).for_each(|a, &b| *a += b); + }) }); } -#[bench] -fn add_2d_one_transposed(bench: &mut test::Bencher) { +fn add_2d_one_transposed(c: &mut Criterion) +{ let mut a = Array::::zeros((ADD2DSZ, ADD2DSZ)); a.swap_axes(0, 1); let b = Array::::zeros((ADD2DSZ, ADD2DSZ)); - bench.iter(|| { - a += &b; + c.bench_function("add_2d_one_transposed", |bn| { + bn.iter(|| { + a += &b; + }) }); } -#[bench] -fn add_2d_zip_one_transposed(bench: &mut test::Bencher) { +fn add_2d_zip_one_transposed(c: &mut Criterion) +{ let mut a = Array::::zeros((ADD2DSZ, ADD2DSZ)); a.swap_axes(0, 1); let b = Array::::zeros((ADD2DSZ, ADD2DSZ)); - bench.iter(|| { - Zip::from(&mut a).and(&b).for_each(|a, &b| *a += b); + c.bench_function("add_2d_zip_one_transposed", |bn| { + bn.iter(|| { + Zip::from(&mut a).and(&b).for_each(|a, &b| *a += b); + }) }); } -#[bench] -fn add_2d_both_transposed(bench: &mut test::Bencher) { +fn add_2d_both_transposed(c: &mut Criterion) +{ let mut a = Array::::zeros((ADD2DSZ, ADD2DSZ)); a.swap_axes(0, 1); let mut b = Array::::zeros((ADD2DSZ, ADD2DSZ)); b.swap_axes(0, 1); - bench.iter(|| { - a += &b; + c.bench_function("add_2d_both_transposed", |bn| { + bn.iter(|| { + a += &b; + }) }); } -#[bench] -fn add_2d_zip_both_transposed(bench: &mut test::Bencher) { +fn add_2d_zip_both_transposed(c: &mut Criterion) +{ let mut a = Array::::zeros((ADD2DSZ, ADD2DSZ)); a.swap_axes(0, 1); let mut b = Array::::zeros((ADD2DSZ, ADD2DSZ)); b.swap_axes(0, 1); - bench.iter(|| { - Zip::from(&mut a).and(&b).for_each(|a, &b| *a += b); + c.bench_function("add_2d_zip_both_transposed", |bn| { + bn.iter(|| { + Zip::from(&mut a).and(&b).for_each(|a, &b| *a += b); + }) }); } -#[bench] -fn add_2d_f32_regular(bench: &mut test::Bencher) { +fn add_2d_f32_regular(c: &mut Criterion) +{ let mut a = Array::::zeros((ADD2DSZ, ADD2DSZ)); let b = Array::::zeros((ADD2DSZ, ADD2DSZ)); let bv = b.view(); - bench.iter(|| { - a += &bv; + c.bench_function("add_2d_f32_regular", |bn| { + bn.iter(|| { + a += &bv; + }) }); } const ADD3DSZ: usize = 16; -#[bench] -fn add_3d_strided(bench: &mut test::Bencher) { +fn add_3d_strided(c: &mut Criterion) +{ let mut a = Array::::zeros((ADD3DSZ, ADD3DSZ, ADD3DSZ * 2)); let mut a = a.slice_mut(s![.., .., ..;2]); let b = Array::::zeros(a.dim()); let bv = b.view(); - bench.iter(|| { - a += &bv; + c.bench_function("add_3d_strided", |bn| { + bn.iter(|| { + a += &bv; + }) }); } -#[bench] -fn add_3d_strided_dyn(bench: &mut test::Bencher) { +fn add_3d_strided_dyn(c: &mut Criterion) +{ let mut a = Array::::zeros(&[ADD3DSZ, ADD3DSZ, ADD3DSZ * 2][..]); let mut a = a.slice_mut(s![.., .., ..;2]); let b = Array::::zeros(a.dim()); let bv = b.view(); - bench.iter(|| { - a += &bv; + c.bench_function("add_3d_strided_dyn", |bn| { + bn.iter(|| { + a += &bv; + }) }); } const ADD1D_SIZE: usize = 64 * 64; -#[bench] -fn add_1d_regular(bench: &mut test::Bencher) { +fn add_1d_regular(c: &mut Criterion) +{ let mut a = Array::::zeros(ADD1D_SIZE); let b = Array::::zeros(a.dim()); - bench.iter(|| { - a += &b; + c.bench_function("add_1d_regular", |bn| { + bn.iter(|| { + a += &b; + }) }); } -#[bench] -fn add_1d_strided(bench: &mut test::Bencher) { +fn add_1d_strided(c: &mut Criterion) +{ let mut a = Array::::zeros(ADD1D_SIZE * 2); let mut av = a.slice_mut(s![..;2]); let b = Array::::zeros(av.dim()); - bench.iter(|| { - av += &b; + c.bench_function("add_1d_strided", |bn| { + bn.iter(|| { + av += &b; + }) }); } -#[bench] -fn iadd_scalar_2d_regular(bench: &mut test::Bencher) { +fn iadd_scalar_2d_regular(c: &mut Criterion) +{ let mut a = Array::::zeros((ADD2DSZ, ADD2DSZ)); - bench.iter(|| { - a += 1.; + c.bench_function("iadd_scalar_2d_regular", |bn| { + bn.iter(|| { + a += 1.; + }) }); } -#[bench] -fn iadd_scalar_2d_strided(bench: &mut test::Bencher) { +fn iadd_scalar_2d_strided(c: &mut Criterion) +{ let mut a = Array::::zeros((ADD2DSZ, ADD2DSZ * 2)); let mut a = a.slice_mut(s![.., ..;2]); - bench.iter(|| { - a += 1.; + c.bench_function("iadd_scalar_2d_strided", |bn| { + bn.iter(|| { + a += 1.; + }) }); } -#[bench] -fn iadd_scalar_2d_regular_dyn(bench: &mut test::Bencher) { +fn iadd_scalar_2d_regular_dyn(c: &mut Criterion) +{ let mut a = Array::::zeros(vec![ADD2DSZ, ADD2DSZ]); - bench.iter(|| { - a += 1.; + c.bench_function("iadd_scalar_2d_regular_dyn", |bn| { + bn.iter(|| { + a += 1.; + }) }); } -#[bench] -fn iadd_scalar_2d_strided_dyn(bench: &mut test::Bencher) { +fn iadd_scalar_2d_strided_dyn(c: &mut Criterion) +{ let mut a = Array::::zeros(vec![ADD2DSZ, ADD2DSZ * 2]); let mut a = a.slice_mut(s![.., ..;2]); - bench.iter(|| { - a += 1.; + c.bench_function("iadd_scalar_2d_strided_dyn", |bn| { + bn.iter(|| { + a += 1.; + }) }); } -#[bench] -fn scaled_add_2d_f32_regular(bench: &mut test::Bencher) { +fn scaled_add_2d_f32_regular(c: &mut Criterion) +{ let mut av = Array::::zeros((ADD2DSZ, ADD2DSZ)); let bv = Array::::zeros((ADD2DSZ, ADD2DSZ)); let scalar = std::f32::consts::PI; - bench.iter(|| { - av.scaled_add(scalar, &bv); + c.bench_function("scaled_add_2d_f32_regular", |bn| { + bn.iter(|| { + av.scaled_add(scalar, &bv); + }) }); } -#[bench] -fn assign_scalar_2d_corder(bench: &mut test::Bencher) { +fn assign_scalar_2d_corder(c: &mut Criterion) +{ let a = Array::zeros((ADD2DSZ, ADD2DSZ)); let mut a = black_box(a); let s = 3.; - bench.iter(move || a.fill(s)) + c.bench_function("assign_scalar_2d_corder", |bn| bn.iter(|| a.fill(s))); } -#[bench] -fn assign_scalar_2d_cutout(bench: &mut test::Bencher) { +fn assign_scalar_2d_cutout(c: &mut Criterion) +{ let mut a = Array::zeros((66, 66)); let a = a.slice_mut(s![1..-1, 1..-1]); let mut a = black_box(a); let s = 3.; - bench.iter(move || a.fill(s)) + c.bench_function("assign_scalar_2d_cutout", |bn| bn.iter(|| a.fill(s))); } -#[bench] -fn assign_scalar_2d_forder(bench: &mut test::Bencher) { +fn assign_scalar_2d_forder(c: &mut Criterion) +{ let mut a = Array::zeros((ADD2DSZ, ADD2DSZ)); a.swap_axes(0, 1); let mut a = black_box(a); let s = 3.; - bench.iter(move || a.fill(s)) + c.bench_function("assign_scalar_2d_forder", |bn| bn.iter(|| a.fill(s))); } -#[bench] -fn assign_zero_2d_corder(bench: &mut test::Bencher) { +fn assign_zero_2d_corder(c: &mut Criterion) +{ let a = Array::zeros((ADD2DSZ, ADD2DSZ)); let mut a = black_box(a); - bench.iter(|| a.fill(0.)) + c.bench_function("assign_zero_2d_corder", |bn| bn.iter(|| a.fill(0.))); } -#[bench] -fn assign_zero_2d_cutout(bench: &mut test::Bencher) { +fn assign_zero_2d_cutout(c: &mut Criterion) +{ let mut a = Array::zeros((66, 66)); let a = a.slice_mut(s![1..-1, 1..-1]); let mut a = black_box(a); - bench.iter(|| a.fill(0.)) + c.bench_function("assign_zero_2d_cutout", |bn| bn.iter(|| a.fill(0.))); } -#[bench] -fn assign_zero_2d_forder(bench: &mut test::Bencher) { +fn assign_zero_2d_forder(c: &mut Criterion) +{ let mut a = Array::zeros((ADD2DSZ, ADD2DSZ)); a.swap_axes(0, 1); let mut a = black_box(a); - bench.iter(|| a.fill(0.)) + c.bench_function("assign_zero_2d_forder", |bn| bn.iter(|| a.fill(0.))); } -#[bench] -fn bench_iter_diag(bench: &mut test::Bencher) { +fn bench_iter_diag(c: &mut Criterion) +{ let a = Array::::zeros((1024, 1024)); - bench.iter(|| { - for elt in a.diag() { - black_box(elt); - } - }) + c.bench_function("bench_iter_diag", |bn| { + bn.iter(|| { + for elt in a.diag() { + black_box(elt); + } + }) + }); } -#[bench] -fn bench_row_iter(bench: &mut test::Bencher) { +fn bench_row_iter(c: &mut Criterion) +{ let a = Array::::zeros((1024, 1024)); let it = a.row(17); - bench.iter(|| { - for elt in it { - black_box(elt); - } - }) + c.bench_function("bench_row_iter", |bn| { + bn.iter(|| { + for elt in it { + black_box(elt); + } + }) + }); } -#[bench] -fn bench_col_iter(bench: &mut test::Bencher) { +fn bench_col_iter(c: &mut Criterion) +{ let a = Array::::zeros((1024, 1024)); let it = a.column(17); - bench.iter(|| { - for elt in it { - black_box(elt); - } - }) + c.bench_function("bench_col_iter", |bn| { + bn.iter(|| { + for elt in it { + black_box(elt); + } + }) + }); } macro_rules! mat_mul { ($modname:ident, $ty:ident, $(($name:ident, $m:expr, $n:expr, $k:expr))+) => { mod $modname { - use test::{black_box, Bencher}; + use criterion::{black_box, Criterion}; use ndarray::Array; $( - #[bench] - fn $name(bench: &mut Bencher) - { + pub fn $name(c: &mut Criterion) { let a = Array::<$ty, _>::zeros(($m, $n)); let b = Array::<$ty, _>::zeros(($n, $k)); let a = black_box(a.view()); let b = black_box(b.view()); - bench.iter(|| a.dot(&b)); + let bench_name = concat!(stringify!($modname), "::", stringify!($name)); + c.bench_function(bench_name, |bn| bn.iter(|| a.dot(&b))); } )+ + pub fn group(c: &mut Criterion) { + $( $name(c); )+ + } } }; } @@ -779,123 +883,126 @@ mat_mul! {mat_mul_i32, i32, (m127, 127, 127, 127) } -#[bench] -fn create_iter_4d(bench: &mut test::Bencher) { +fn create_iter_4d(c: &mut Criterion) +{ let mut a = Array::from_elem((4, 5, 3, 2), 1.0); a.swap_axes(0, 1); a.swap_axes(2, 1); let v = black_box(a.view()); - bench.iter(|| v.into_iter()); + c.bench_function("create_iter_4d", |bn| bn.iter(|| v.into_iter())); } -#[bench] -fn bench_to_owned_n(bench: &mut test::Bencher) { +fn bench_to_owned_n(c: &mut Criterion) +{ let a = Array::::zeros((32, 32)); - bench.iter(|| a.to_owned()); + c.bench_function("bench_to_owned_n", |bn| bn.iter(|| a.to_owned())); } -#[bench] -fn bench_to_owned_t(bench: &mut test::Bencher) { +fn bench_to_owned_t(c: &mut Criterion) +{ let mut a = Array::::zeros((32, 32)); a.swap_axes(0, 1); - bench.iter(|| a.to_owned()); + c.bench_function("bench_to_owned_t", |bn| bn.iter(|| a.to_owned())); } -#[bench] -fn bench_to_owned_strided(bench: &mut test::Bencher) { +fn bench_to_owned_strided(c: &mut Criterion) +{ let a = Array::::zeros((32, 64)); let a = a.slice(s![.., ..;2]); - bench.iter(|| a.to_owned()); + c.bench_function("bench_to_owned_strided", |bn| bn.iter(|| a.to_owned())); } -#[bench] -fn equality_i32(bench: &mut test::Bencher) { + +fn equality_i32(c: &mut Criterion) +{ let a = Array::::zeros((64, 64)); let b = Array::::zeros((64, 64)); - bench.iter(|| a == b); + c.bench_function("equality_i32", |bn| bn.iter(|| a == b)); } -#[bench] -fn equality_f32(bench: &mut test::Bencher) { +fn equality_f32(c: &mut Criterion) +{ let a = Array::::zeros((64, 64)); let b = Array::::zeros((64, 64)); - bench.iter(|| a == b); + c.bench_function("equality_f32", |bn| bn.iter(|| a == b)); } -#[bench] -fn equality_f32_mixorder(bench: &mut test::Bencher) { +fn equality_f32_mixorder(c: &mut Criterion) +{ let a = Array::::zeros((64, 64)); let b = Array::::zeros((64, 64).f()); - bench.iter(|| a == b); + c.bench_function("equality_f32_mixorder", |bn| bn.iter(|| a == b)); } -#[bench] -fn dot_f32_16(bench: &mut test::Bencher) { +fn dot_f32_16(c: &mut Criterion) +{ let a = Array::::zeros(16); let b = Array::::zeros(16); - bench.iter(|| a.dot(&b)); + c.bench_function("dot_f32_16", |bn| bn.iter(|| a.dot(&b))); } -#[bench] -fn dot_f32_20(bench: &mut test::Bencher) { +fn dot_f32_20(c: &mut Criterion) +{ let a = Array::::zeros(20); let b = Array::::zeros(20); - bench.iter(|| a.dot(&b)); + c.bench_function("dot_f32_20", |bn| bn.iter(|| a.dot(&b))); } -#[bench] -fn dot_f32_32(bench: &mut test::Bencher) { +fn dot_f32_32(c: &mut Criterion) +{ let a = Array::::zeros(32); let b = Array::::zeros(32); - bench.iter(|| a.dot(&b)); + c.bench_function("dot_f32_32", |bn| bn.iter(|| a.dot(&b))); } -#[bench] -fn dot_f32_256(bench: &mut test::Bencher) { +fn dot_f32_256(c: &mut Criterion) +{ let a = Array::::zeros(256); let b = Array::::zeros(256); - bench.iter(|| a.dot(&b)); + c.bench_function("dot_f32_256", |bn| bn.iter(|| a.dot(&b))); } -#[bench] -fn dot_f32_1024(bench: &mut test::Bencher) { +fn dot_f32_1024(c: &mut Criterion) +{ let av = Array::::zeros(1024); let bv = Array::::zeros(1024); - bench.iter(|| av.dot(&bv)); + c.bench_function("dot_f32_1024", |bn| bn.iter(|| av.dot(&bv))); } -#[bench] -fn dot_f32_10e6(bench: &mut test::Bencher) { +fn dot_f32_10e6(c: &mut Criterion) +{ let n = 1_000_000; let av = Array::::zeros(n); let bv = Array::::zeros(n); - bench.iter(|| av.dot(&bv)); + c.bench_function("dot_f32_10e6", |bn| bn.iter(|| av.dot(&bv))); } -#[bench] -fn dot_extended(bench: &mut test::Bencher) { +fn dot_extended(c: &mut Criterion) +{ let m = 10; let n = 33; let k = 10; let av = Array::::zeros((m, n)); let bv = Array::::zeros((n, k)); let mut res = Array::::zeros((m, k)); - // make a manual simple matrix multiply to test - bench.iter(|| { - for i in 0..m { - for j in 0..k { - unsafe { - *res.uget_mut((i, j)) = av.row(i).dot(&bv.column(j)); + c.bench_function("dot_extended", |bn| { + bn.iter(|| { + for i in 0..m { + for j in 0..k { + unsafe { + *res.uget_mut((i, j)) = av.row(i).dot(&bv.column(j)); + } } } - } - }) + }) + }); } const MEAN_SUM_N: usize = 127; #[cfg(feature = "std")] -fn range_mat(m: Ix, n: Ix) -> Array2 { +fn range_mat(m: Ix, n: Ix) -> Array2 +{ assert!(m * n != 0); Array::linspace(0.0..=(m * n - 1) as f32, m * n) .into_shape_with_order((m, n)) @@ -903,103 +1010,290 @@ fn range_mat(m: Ix, n: Ix) -> Array2 { } #[cfg(feature = "std")] -#[bench] -fn mean_axis0(bench: &mut test::Bencher) { +fn mean_axis0(c: &mut Criterion) +{ let a = range_mat(MEAN_SUM_N, MEAN_SUM_N); - bench.iter(|| a.mean_axis(Axis(0))); + c.bench_function("mean_axis0", |bn| bn.iter(|| a.mean_axis(Axis(0)))); } #[cfg(feature = "std")] -#[bench] -fn mean_axis1(bench: &mut test::Bencher) { +fn mean_axis1(c: &mut Criterion) +{ let a = range_mat(MEAN_SUM_N, MEAN_SUM_N); - bench.iter(|| a.mean_axis(Axis(1))); + c.bench_function("mean_axis1", |bn| bn.iter(|| a.mean_axis(Axis(1)))); } #[cfg(feature = "std")] -#[bench] -fn sum_axis0(bench: &mut test::Bencher) { +fn sum_axis0(c: &mut Criterion) +{ let a = range_mat(MEAN_SUM_N, MEAN_SUM_N); - bench.iter(|| a.sum_axis(Axis(0))); + c.bench_function("sum_axis0", |bn| bn.iter(|| a.sum_axis(Axis(0)))); } #[cfg(feature = "std")] -#[bench] -fn sum_axis1(bench: &mut test::Bencher) { +fn sum_axis1(c: &mut Criterion) +{ let a = range_mat(MEAN_SUM_N, MEAN_SUM_N); - bench.iter(|| a.sum_axis(Axis(1))); + c.bench_function("sum_axis1", |bn| bn.iter(|| a.sum_axis(Axis(1)))); } -#[bench] -fn into_dimensionality_ix1_ok(bench: &mut test::Bencher) { +fn into_dimensionality_ix1_ok(c: &mut Criterion) +{ let a = Array::::zeros(Ix1(10)); let a = a.view(); - bench.iter(|| a.into_dimensionality::()); + c.bench_function("into_dimensionality_ix1_ok", |bn| { + bn.iter(|| a.into_dimensionality::()) + }); } -#[bench] -fn into_dimensionality_ix3_ok(bench: &mut test::Bencher) { +fn into_dimensionality_ix3_ok(c: &mut Criterion) +{ let a = Array::::zeros(Ix3(10, 10, 10)); let a = a.view(); - bench.iter(|| a.into_dimensionality::()); + c.bench_function("into_dimensionality_ix3_ok", |bn| { + bn.iter(|| a.into_dimensionality::()) + }); } -#[bench] -fn into_dimensionality_ix3_err(bench: &mut test::Bencher) { +fn into_dimensionality_ix3_err(c: &mut Criterion) +{ let a = Array::::zeros(Ix3(10, 10, 10)); let a = a.view(); - bench.iter(|| a.into_dimensionality::()); + c.bench_function("into_dimensionality_ix3_err", |bn| { + bn.iter(|| a.into_dimensionality::()) + }); } -#[bench] -fn into_dimensionality_dyn_to_ix3(bench: &mut test::Bencher) { +fn into_dimensionality_dyn_to_ix3(c: &mut Criterion) +{ let a = Array::::zeros(IxDyn(&[10, 10, 10])); let a = a.view(); - bench.iter(|| a.clone().into_dimensionality::()); + c.bench_function("into_dimensionality_dyn_to_ix3", |bn| { + bn.iter(|| a.clone().into_dimensionality::()) + }); } -#[bench] -fn into_dimensionality_dyn_to_dyn(bench: &mut test::Bencher) { +fn into_dimensionality_dyn_to_dyn(c: &mut Criterion) +{ let a = Array::::zeros(IxDyn(&[10, 10, 10])); let a = a.view(); - bench.iter(|| a.clone().into_dimensionality::()); + c.bench_function("into_dimensionality_dyn_to_dyn", |bn| { + bn.iter(|| a.clone().into_dimensionality::()) + }); } -#[bench] -fn into_dyn_ix3(bench: &mut test::Bencher) { +fn into_dyn_ix3(c: &mut Criterion) +{ let a = Array::::zeros(Ix3(10, 10, 10)); let a = a.view(); - bench.iter(|| a.into_dyn()); + c.bench_function("into_dyn_ix3", |bn| bn.iter(|| a.into_dyn())); } -#[bench] -fn into_dyn_ix5(bench: &mut test::Bencher) { +fn into_dyn_ix5(c: &mut Criterion) +{ let a = Array::::zeros(Ix5(2, 2, 2, 2, 2)); let a = a.view(); - bench.iter(|| a.into_dyn()); + c.bench_function("into_dyn_ix5", |bn| bn.iter(|| a.into_dyn())); } -#[bench] -fn into_dyn_dyn(bench: &mut test::Bencher) { +fn into_dyn_dyn(c: &mut Criterion) +{ let a = Array::::zeros(IxDyn(&[10, 10, 10])); let a = a.view(); - bench.iter(|| a.clone().into_dyn()); + c.bench_function("into_dyn_dyn", |bn| bn.iter(|| a.clone().into_dyn())); } -#[bench] -fn broadcast_same_dim(bench: &mut test::Bencher) { +fn broadcast_same_dim(c: &mut Criterion) +{ let s = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; let s = Array4::from_shape_vec((2, 2, 3, 2), s.to_vec()).unwrap(); let a = s.slice(s![.., ..;-1, ..;2, ..]); let b = s.slice(s![.., .., ..;2, ..]); - bench.iter(|| &a + &b); + c.bench_function("broadcast_same_dim", |bn| bn.iter(|| &a + &b)); } -#[bench] -fn broadcast_one_side(bench: &mut test::Bencher) { +fn broadcast_one_side(c: &mut Criterion) +{ let s = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; let s2 = [1, 2, 3, 4, 5, 6]; let a = Array4::from_shape_vec((4, 1, 3, 2), s.to_vec()).unwrap(); let b = Array3::from_shape_vec((1, 3, 2), s2.to_vec()).unwrap(); - bench.iter(|| &a + &b); -} + c.bench_function("broadcast_one_side", |bn| bn.iter(|| &a + &b)); +} + +criterion_group!( + iter_benches, + iter_sum_1d_regular, + iter_sum_1d_raw, + iter_sum_2d_regular, + iter_sum_2d_by_row, + iter_sum_2d_raw, + iter_sum_2d_cutout, + iter_sum_2d_cutout_by_row, + iter_sum_2d_cutout_outer_iter, + iter_sum_2d_transpose_regular, + iter_sum_2d_transpose_by_row, +); + +criterion_group!( + sum_benches, + sum_2d_regular, + sum_2d_cutout, + sum_2d_float, + sum_2d_float_cutout, + sum_2d_float_t_cutout, + fold_sum_i32_2d_regular, + fold_sum_i32_2d_cutout, + fold_sum_i32_2d_stride, + fold_sum_i32_2d_transpose, + fold_sum_i32_2d_cutout_transpose, +); + +criterion_group!( + add_benches, + add_2d_regular, + add_2d_zip, + add_2d_alloc_plus, + add_2d_alloc_zip_uninit, + add_2d_alloc_zip_collect, + vec_string_collect, + array_string_collect, + vec_f64_collect, + array_f64_collect, + add_2d_assign_ops, + add_2d_cutout, + add_2d_zip_cutout, + add_2d_cutouts_by_4, + add_2d_cutouts_by_16, + add_2d_cutouts_by_32, + add_2d_broadcast_1_to_2, + add_2d_broadcast_0_to_2, +); + +criterion_group!( + scalar_benches, + scalar_toowned, + scalar_add_1, + scalar_add_2, + scalar_add_strided_1, + scalar_add_strided_2, + scalar_sub_1, + scalar_sub_2, + add_2d_0_to_2_iadd_scalar, +); + +criterion_group!( + add_strided_benches, + add_2d_strided, + add_2d_regular_dyn, + add_2d_strided_dyn, + add_2d_zip_strided, + add_2d_one_transposed, + add_2d_zip_one_transposed, + add_2d_both_transposed, + add_2d_zip_both_transposed, + add_2d_f32_regular, + add_3d_strided, + add_3d_strided_dyn, + add_1d_regular, + add_1d_strided, +); + +criterion_group!( + iadd_scalar_benches, + iadd_scalar_2d_regular, + iadd_scalar_2d_strided, + iadd_scalar_2d_regular_dyn, + iadd_scalar_2d_strided_dyn, + scaled_add_2d_f32_regular, + assign_scalar_2d_corder, + assign_scalar_2d_cutout, + assign_scalar_2d_forder, + assign_zero_2d_corder, + assign_zero_2d_cutout, + assign_zero_2d_forder, +); + +criterion_group!( + iter_misc_benches, + bench_iter_diag, + bench_row_iter, + bench_col_iter, + create_iter_4d, + bench_to_owned_n, + bench_to_owned_t, + bench_to_owned_strided, + equality_i32, + equality_f32, + equality_f32_mixorder, +); + +criterion_group!( + dot_benches, + dot_f32_16, + dot_f32_20, + dot_f32_32, + dot_f32_256, + dot_f32_1024, + dot_f32_10e6, + dot_extended, +); + +criterion_group!( + dimensionality_benches, + into_dimensionality_ix1_ok, + into_dimensionality_ix3_ok, + into_dimensionality_ix3_err, + into_dimensionality_dyn_to_ix3, + into_dimensionality_dyn_to_dyn, + into_dyn_ix3, + into_dyn_ix5, + into_dyn_dyn, + broadcast_same_dim, + broadcast_one_side, +); + +criterion_group!( + matmul_benches, + mat_mul_f32::group, + mat_mul_f64::group, + mat_mul_i32::group, +); + +#[cfg(feature = "std")] +criterion_group!( + std_benches, + mean_axis0, + mean_axis1, + sum_axis0, + sum_axis1, +); + +#[cfg(feature = "std")] +criterion_main!( + iter_benches, + sum_benches, + add_benches, + scalar_benches, + add_strided_benches, + iadd_scalar_benches, + iter_misc_benches, + dot_benches, + dimensionality_benches, + matmul_benches, + std_benches, +); + +#[cfg(not(feature = "std"))] +criterion_main!( + iter_benches, + sum_benches, + add_benches, + scalar_benches, + add_strided_benches, + iadd_scalar_benches, + iter_misc_benches, + dot_benches, + dimensionality_benches, + matmul_benches, +); diff --git a/benches/chunks.rs b/benches/chunks.rs index 5ea9ba46..702727c9 100644 --- a/benches/chunks.rs +++ b/benches/chunks.rs @@ -1,82 +1,98 @@ -#![feature(test)] - -extern crate test; -use test::Bencher; - +use criterion::{criterion_group, criterion_main, Criterion}; use ndarray::prelude::*; use ndarray::NdProducer; -#[bench] -fn chunk2x2_iter_sum(bench: &mut Bencher) { +fn chunk2x2_iter_sum(c: &mut Criterion) +{ let a = Array::::zeros((256, 256)); let chunksz = (2, 2); let mut sum = Array::zeros(a.exact_chunks(chunksz).raw_dim()); - bench.iter(|| { - azip!((a in a.exact_chunks(chunksz), sum in &mut sum) { - *sum = a.iter().sum::(); + c.bench_function("chunk2x2_iter_sum", |b| { + b.iter(|| { + azip!((a in a.exact_chunks(chunksz), sum in &mut sum) { + *sum = a.iter().sum::(); + }); }); }); } -#[bench] -fn chunk2x2_sum(bench: &mut Bencher) { +fn chunk2x2_sum(c: &mut Criterion) +{ let a = Array::::zeros((256, 256)); let chunksz = (2, 2); let mut sum = Array::zeros(a.exact_chunks(chunksz).raw_dim()); - bench.iter(|| { - azip!((a in a.exact_chunks(chunksz), sum in &mut sum) { - *sum = a.sum(); + c.bench_function("chunk2x2_sum", |b| { + b.iter(|| { + azip!((a in a.exact_chunks(chunksz), sum in &mut sum) { + *sum = a.sum(); + }); }); }); } -#[bench] -fn chunk2x2_sum_get1(bench: &mut Bencher) { +fn chunk2x2_sum_get1(c: &mut Criterion) +{ let a = Array::::zeros((256, 256)); let chunksz = (2, 2); let mut sum = Array::::zeros(a.exact_chunks(chunksz).raw_dim()); - bench.iter(|| { - let (m, n) = a.dim(); - for i in 0..m { - for j in 0..n { - sum[[i / 2, j / 2]] += a[[i, j]]; + c.bench_function("chunk2x2_sum_get1", |b| { + b.iter(|| { + let (m, n) = a.dim(); + for i in 0..m { + for j in 0..n { + sum[[i / 2, j / 2]] += a[[i, j]]; + } } - } + }); }); } -#[bench] -fn chunk2x2_sum_uget1(bench: &mut Bencher) { +fn chunk2x2_sum_uget1(c: &mut Criterion) +{ let a = Array::::zeros((256, 256)); let chunksz = (2, 2); let mut sum = Array::::zeros(a.exact_chunks(chunksz).raw_dim()); - bench.iter(|| { - let (m, n) = a.dim(); - for i in 0..m { - for j in 0..n { - unsafe { - *sum.uget_mut([i / 2, j / 2]) += *a.uget([i, j]); + c.bench_function("chunk2x2_sum_uget1", |b| { + b.iter(|| { + let (m, n) = a.dim(); + for i in 0..m { + for j in 0..n { + unsafe { + *sum.uget_mut([i / 2, j / 2]) += *a.uget([i, j]); + } } } - } + }); }); } -#[bench] #[allow(clippy::identity_op)] -fn chunk2x2_sum_get2(bench: &mut Bencher) { +fn chunk2x2_sum_get2(c: &mut Criterion) +{ let a = Array::::zeros((256, 256)); let chunksz = (2, 2); let mut sum = Array::::zeros(a.exact_chunks(chunksz).raw_dim()); - bench.iter(|| { - let (m, n) = sum.dim(); - for i in 0..m { - for j in 0..n { - sum[[i, j]] += a[[i * 2 + 0, j * 2 + 0]]; - sum[[i, j]] += a[[i * 2 + 0, j * 2 + 1]]; - sum[[i, j]] += a[[i * 2 + 1, j * 2 + 1]]; - sum[[i, j]] += a[[i * 2 + 1, j * 2 + 0]]; + c.bench_function("chunk2x2_sum_get2", |b| { + b.iter(|| { + let (m, n) = sum.dim(); + for i in 0..m { + for j in 0..n { + sum[[i, j]] += a[[i * 2 + 0, j * 2 + 0]]; + sum[[i, j]] += a[[i * 2 + 0, j * 2 + 1]]; + sum[[i, j]] += a[[i * 2 + 1, j * 2 + 1]]; + sum[[i, j]] += a[[i * 2 + 1, j * 2 + 0]]; + } } - } + }); }); } + +criterion_group!( + benches, + chunk2x2_iter_sum, + chunk2x2_sum, + chunk2x2_sum_get1, + chunk2x2_sum_uget1, + chunk2x2_sum_get2 +); +criterion_main!(benches); diff --git a/benches/construct.rs b/benches/construct.rs index b06983b2..3cc53650 100644 --- a/benches/construct.rs +++ b/benches/construct.rs @@ -1,35 +1,43 @@ -#![feature(test)] #![allow(clippy::many_single_char_names, clippy::deref_addrof, clippy::unreadable_literal)] -extern crate test; -use test::Bencher; +use criterion::{black_box, criterion_group, criterion_main, Criterion}; use ndarray::prelude::*; -#[bench] -fn default_f64(bench: &mut Bencher) { - bench.iter(|| Array::::default((128, 128))) +fn default_f64(c: &mut Criterion) { + c.bench_function("default_f64", |b| { + b.iter(|| Array::::default(black_box((128, 128)))) + }); } -#[bench] -fn zeros_f64(bench: &mut Bencher) { - bench.iter(|| Array::::zeros((128, 128))) +fn zeros_f64(c: &mut Criterion) { + c.bench_function("zeros_f64", |b| { + b.iter(|| Array::::zeros(black_box((128, 128)))) + }); } #[cfg(feature = "std")] -#[bench] -fn map_regular(bench: &mut test::Bencher) { +fn map_regular(c: &mut Criterion) { let a = Array::linspace(0.0..=127.0, 128) .into_shape_with_order((8, 16)) .unwrap(); - bench.iter(|| a.map(|&x| 2. * x)); + c.bench_function("map_regular", |b| { + b.iter(|| black_box(&a).map(|&x| 2. * x)) + }); } #[cfg(feature = "std")] -#[bench] -fn map_stride(bench: &mut test::Bencher) { +fn map_stride(c: &mut Criterion) { let a = Array::linspace(0.0..=127.0, 256) .into_shape_with_order((8, 32)) .unwrap(); let av = a.slice(s![.., ..;2]); - bench.iter(|| av.map(|&x| 2. * x)); + c.bench_function("map_stride", |b| { + b.iter(|| black_box(&av).map(|&x| 2. * x)) + }); } + +#[cfg(feature = "std")] +criterion_group!(benches, default_f64, zeros_f64, map_regular, map_stride); +#[cfg(not(feature = "std"))] +criterion_group!(benches, default_f64, zeros_f64); +criterion_main!(benches); diff --git a/benches/gemv_gemm.rs b/benches/gemv_gemm.rs index 0569c2ec..4b7bc19c 100644 --- a/benches/gemv_gemm.rs +++ b/benches/gemv_gemm.rs @@ -1,9 +1,6 @@ -#![feature(test)] #![allow(clippy::many_single_char_names, clippy::deref_addrof, clippy::unreadable_literal)] -extern crate test; -use test::Bencher; - +use criterion::{criterion_group, criterion_main, Criterion}; use num_complex::Complex; use num_traits::{Float, One, Zero}; @@ -13,59 +10,69 @@ use ndarray::linalg::general_mat_mul; use ndarray::linalg::general_mat_vec_mul; use ndarray::LinalgScalar; -#[bench] -fn gemv_64_64c(bench: &mut Bencher) { +fn gemv_64_64c(c: &mut Criterion) +{ let a = Array::zeros((64, 64)); let (m, n) = a.dim(); let x = Array::zeros(n); let mut y = Array::zeros(m); - bench.iter(|| { - general_mat_vec_mul(1.0, &a, &x, 1.0, &mut y); + c.bench_function("gemv_64_64c", |b| { + b.iter(|| { + general_mat_vec_mul(1.0, &a, &x, 1.0, &mut y); + }); }); } -#[bench] -fn gemv_64_64f(bench: &mut Bencher) { +fn gemv_64_64f(c: &mut Criterion) +{ let a = Array::zeros((64, 64).f()); let (m, n) = a.dim(); let x = Array::zeros(n); let mut y = Array::zeros(m); - bench.iter(|| { - general_mat_vec_mul(1.0, &a, &x, 1.0, &mut y); + c.bench_function("gemv_64_64f", |b| { + b.iter(|| { + general_mat_vec_mul(1.0, &a, &x, 1.0, &mut y); + }); }); } -#[bench] -fn gemv_64_32(bench: &mut Bencher) { +fn gemv_64_32(c: &mut Criterion) +{ let a = Array::zeros((64, 32)); let (m, n) = a.dim(); let x = Array::zeros(n); let mut y = Array::zeros(m); - bench.iter(|| { - general_mat_vec_mul(1.0, &a, &x, 1.0, &mut y); + c.bench_function("gemv_64_32", |b| { + b.iter(|| { + general_mat_vec_mul(1.0, &a, &x, 1.0, &mut y); + }); }); } -#[bench] -fn cgemm_100(bench: &mut Bencher) { - cgemm_bench::(100, bench); +fn cgemm_100(c: &mut Criterion) +{ + cgemm_bench::("cgemm_100", 100, c); } -#[bench] -fn zgemm_100(bench: &mut Bencher) { - cgemm_bench::(100, bench); +fn zgemm_100(c: &mut Criterion) +{ + cgemm_bench::("zgemm_100", 100, c); } -fn cgemm_bench(size: usize, bench: &mut Bencher) -where - A: LinalgScalar + Float, +fn cgemm_bench(name: &str, size: usize, c: &mut Criterion) +where A: LinalgScalar + Float { let (m, k, n) = (size, size, size); let a = Array::, _>::zeros((m, k)); let x = Array::zeros((k, n)); let mut y = Array::zeros((m, n)); - bench.iter(|| { - general_mat_mul(Complex::one(), &a, &x, Complex::zero(), &mut y); + c.bench_function(name, |b| { + b.iter(|| { + general_mat_mul(Complex::one(), &a, &x, Complex::zero(), &mut y); + }); }); } + +criterion_group!(benches, gemv_64_64c, gemv_64_64f, gemv_64_32, cgemm_100, zgemm_100); +criterion_main!(benches); diff --git a/benches/higher-order.rs b/benches/higher-order.rs index f2743101..09bbcbc3 100644 --- a/benches/higher-order.rs +++ b/benches/higher-order.rs @@ -1,9 +1,6 @@ -#![feature(test)] #![allow(clippy::many_single_char_names, clippy::deref_addrof, clippy::unreadable_literal)] -extern crate test; -use test::black_box; -use test::Bencher; +use criterion::{black_box, criterion_group, criterion_main, Criterion}; use ndarray::prelude::*; const N: usize = 1024; @@ -11,75 +8,105 @@ const X: usize = 64; const Y: usize = 16; #[cfg(feature = "std")] -#[bench] -fn map_regular(bench: &mut Bencher) { +fn map_regular(c: &mut Criterion) +{ let a = Array::linspace(0.0..=127.0, N) .into_shape_with_order((X, Y)) .unwrap(); - bench.iter(|| a.map(|&x| 2. * x)); + c.bench_function("map_regular", |b| { + b.iter(|| a.map(|&x| 2. * x)); + }); } -pub fn double_array(mut a: ArrayViewMut2<'_, f64>) { +pub fn double_array(mut a: ArrayViewMut2<'_, f64>) +{ a *= 2.0; } #[cfg(feature = "std")] -#[bench] -fn map_stride_double_f64(bench: &mut Bencher) { +fn map_stride_double_f64(c: &mut Criterion) +{ let mut a = Array::linspace(0.0..=127.0, N * 2) .into_shape_with_order([X, Y * 2]) .unwrap(); let mut av = a.slice_mut(s![.., ..;2]); - bench.iter(|| { - double_array(av.view_mut()); + c.bench_function("map_stride_double_f64", |b| { + b.iter(|| { + double_array(av.view_mut()); + }); }); } #[cfg(feature = "std")] -#[bench] -fn map_stride_f64(bench: &mut Bencher) { +fn map_stride_f64(c: &mut Criterion) +{ let a = Array::linspace(0.0..=127.0, N * 2) .into_shape_with_order([X, Y * 2]) .unwrap(); let av = a.slice(s![.., ..;2]); - bench.iter(|| av.map(|&x| 2. * x)); + c.bench_function("map_stride_f64", |b| { + b.iter(|| av.map(|&x| 2. * x)); + }); } #[cfg(feature = "std")] -#[bench] -fn map_stride_u32(bench: &mut Bencher) { +fn map_stride_u32(c: &mut Criterion) +{ let a = Array::linspace(0.0..=127.0, N * 2) .into_shape_with_order([X, Y * 2]) .unwrap(); let b = a.mapv(|x| x as u32); let av = b.slice(s![.., ..;2]); - bench.iter(|| av.map(|&x| 2 * x)); + c.bench_function("map_stride_u32", |b| { + b.iter(|| av.map(|&x| 2 * x)); + }); } #[cfg(feature = "std")] -#[bench] -fn fold_axis(bench: &mut Bencher) { +fn fold_axis(c: &mut Criterion) +{ let a = Array::linspace(0.0..=127.0, N * 2) .into_shape_with_order([X, Y * 2]) .unwrap(); - bench.iter(|| a.fold_axis(Axis(0), 0., |&acc, &elt| acc + elt)); + c.bench_function("fold_axis", |b| { + b.iter(|| a.fold_axis(Axis(0), 0., |&acc, &elt| acc + elt)); + }); } const MA: usize = 64; const MASZ: usize = MA * MA; -#[bench] -fn map_axis_0(bench: &mut Bencher) { +fn map_axis_0(c: &mut Criterion) +{ let a = Array::from_iter(0..MASZ as i32) .into_shape_with_order([MA, MA]) .unwrap(); - bench.iter(|| a.map_axis(Axis(0), black_box)); + c.bench_function("map_axis_0", |b| { + b.iter(|| a.map_axis(Axis(0), black_box)); + }); } -#[bench] -fn map_axis_1(bench: &mut Bencher) { +fn map_axis_1(c: &mut Criterion) +{ let a = Array::from_iter(0..MASZ as i32) .into_shape_with_order([MA, MA]) .unwrap(); - bench.iter(|| a.map_axis(Axis(1), black_box)); + c.bench_function("map_axis_1", |b| { + b.iter(|| a.map_axis(Axis(1), black_box)); + }); } + +#[cfg(feature = "std")] +criterion_group!( + benches, + map_regular, + map_stride_double_f64, + map_stride_f64, + map_stride_u32, + fold_axis, + map_axis_0, + map_axis_1 +); +#[cfg(not(feature = "std"))] +criterion_group!(benches, map_axis_0, map_axis_1); +criterion_main!(benches); diff --git a/benches/iter.rs b/benches/iter.rs index da18c0d6..6e782002 100644 --- a/benches/iter.rs +++ b/benches/iter.rs @@ -1,203 +1,231 @@ -#![feature(test)] -#![allow(clippy::many_single_char_names, clippy::deref_addrof, clippy::unreadable_literal)] +// `s![1..-1, 1..-1]` — ndarray's `s!` macro uses Python-style negative +// indexing where `-1` means "from end". Clippy can't see through the macro +// and reads `1..-1` as a plain (empty) Rust range; the actual semantics are +// correct. +#![allow(clippy::many_single_char_names, clippy::deref_addrof, clippy::unreadable_literal, clippy::reversed_empty_ranges)] -extern crate test; +use criterion::{black_box, criterion_group, criterion_main, Criterion}; use rawpointer::PointerExt; -use test::black_box; -use test::Bencher; use ndarray::prelude::*; use ndarray::Slice; use ndarray::{FoldWhile, Zip}; -#[bench] -fn iter_sum_2d_regular(bench: &mut Bencher) { +fn iter_sum_2d_regular(c: &mut Criterion) +{ let a = Array::::zeros((64, 64)); - bench.iter(|| a.iter().sum::()); + c.bench_function("iter_sum_2d_regular", |b| b.iter(|| a.iter().sum::())); } -#[bench] -fn iter_sum_2d_cutout(bench: &mut Bencher) { +fn iter_sum_2d_cutout(c: &mut Criterion) +{ let a = Array::::zeros((66, 66)); let av = a.slice(s![1..-1, 1..-1]); let a = av; - bench.iter(|| a.iter().sum::()); + c.bench_function("iter_sum_2d_cutout", |b| b.iter(|| a.iter().sum::())); } -#[bench] -fn iter_all_2d_cutout(bench: &mut Bencher) { +fn iter_all_2d_cutout(c: &mut Criterion) +{ let a = Array::::zeros((66, 66)); let av = a.slice(s![1..-1, 1..-1]); let a = av; - bench.iter(|| a.iter().all(|&x| x >= 0)); + c.bench_function("iter_all_2d_cutout", |b| b.iter(|| a.iter().all(|&x| x >= 0))); } -#[bench] -fn iter_sum_2d_transpose(bench: &mut Bencher) { +fn iter_sum_2d_transpose(c: &mut Criterion) +{ let a = Array::::zeros((66, 66)); let a = a.t(); - bench.iter(|| a.iter().sum::()); + c.bench_function("iter_sum_2d_transpose", |b| b.iter(|| a.iter().sum::())); } #[cfg(feature = "std")] -#[bench] -fn iter_filter_sum_2d_u32(bench: &mut Bencher) { +fn iter_filter_sum_2d_u32(c: &mut Criterion) +{ let a = Array::linspace(0.0..=1.0, 256) .into_shape_with_order((16, 16)) .unwrap(); let b = a.mapv(|x| (x * 100.) as u32); - bench.iter(|| b.iter().filter(|&&x| x < 75).sum::()); + c.bench_function("iter_filter_sum_2d_u32", |bn| { + bn.iter(|| b.iter().filter(|&&x| x < 75).sum::()) + }); } #[cfg(feature = "std")] -#[bench] -fn iter_filter_sum_2d_f32(bench: &mut Bencher) { +fn iter_filter_sum_2d_f32(c: &mut Criterion) +{ let a = Array::linspace(0.0..=1.0, 256) .into_shape_with_order((16, 16)) .unwrap(); let b = a * 100.; - bench.iter(|| b.iter().filter(|&&x| x < 75.).sum::()); + c.bench_function("iter_filter_sum_2d_f32", |bn| { + bn.iter(|| b.iter().filter(|&&x| x < 75.).sum::()) + }); } #[cfg(feature = "std")] -#[bench] -fn iter_filter_sum_2d_stride_u32(bench: &mut Bencher) { +fn iter_filter_sum_2d_stride_u32(c: &mut Criterion) +{ let a = Array::linspace(0.0..=1.0, 256) .into_shape_with_order((16, 16)) .unwrap(); let b = a.mapv(|x| (x * 100.) as u32); let b = b.slice(s![.., ..;2]); - bench.iter(|| b.iter().filter(|&&x| x < 75).sum::()); + c.bench_function("iter_filter_sum_2d_stride_u32", |bn| { + bn.iter(|| b.iter().filter(|&&x| x < 75).sum::()) + }); } #[cfg(feature = "std")] -#[bench] -fn iter_filter_sum_2d_stride_f32(bench: &mut Bencher) { +fn iter_filter_sum_2d_stride_f32(c: &mut Criterion) +{ let a = Array::linspace(0.0..=1.0, 256) .into_shape_with_order((16, 16)) .unwrap(); let b = a * 100.; let b = b.slice(s![.., ..;2]); - bench.iter(|| b.iter().filter(|&&x| x < 75.).sum::()); + c.bench_function("iter_filter_sum_2d_stride_f32", |bn| { + bn.iter(|| b.iter().filter(|&&x| x < 75.).sum::()) + }); } #[cfg(feature = "std")] -#[bench] -fn iter_rev_step_by_contiguous(bench: &mut Bencher) { +fn iter_rev_step_by_contiguous(c: &mut Criterion) +{ let a = Array::linspace(0.0..=1.0, 512); - bench.iter(|| { - a.iter().rev().step_by(2).for_each(|x| { - black_box(x); + c.bench_function("iter_rev_step_by_contiguous", |bn| { + bn.iter(|| { + a.iter().rev().step_by(2).for_each(|x| { + black_box(x); + }) }) }); } #[cfg(feature = "std")] -#[bench] -fn iter_rev_step_by_discontiguous(bench: &mut Bencher) { +fn iter_rev_step_by_discontiguous(c: &mut Criterion) +{ let mut a = Array::linspace(0.0..=1.0, 1024); a.slice_axis_inplace(Axis(0), Slice::new(0, None, 2)); - bench.iter(|| { - a.iter().rev().step_by(2).for_each(|x| { - black_box(x); + c.bench_function("iter_rev_step_by_discontiguous", |bn| { + bn.iter(|| { + a.iter().rev().step_by(2).for_each(|x| { + black_box(x); + }) }) }); } const ZIPSZ: usize = 10_000; -#[bench] -fn sum_3_std_zip1(bench: &mut Bencher) { +fn sum_3_std_zip1(c: &mut Criterion) +{ let a = vec![1; ZIPSZ]; let b = vec![1; ZIPSZ]; - let c = vec![1; ZIPSZ]; - bench.iter(|| { - a.iter() - .zip(b.iter().zip(&c)) - .fold(0, |acc, (&a, (&b, &c))| acc + a + b + c) + let c_vec = vec![1; ZIPSZ]; + c.bench_function("sum_3_std_zip1", |bn| { + bn.iter(|| { + a.iter() + .zip(b.iter().zip(&c_vec)) + .fold(0, |acc, (&a, (&b, &c))| acc + a + b + c) + }) }); } -#[bench] -fn sum_3_std_zip2(bench: &mut Bencher) { +fn sum_3_std_zip2(c: &mut Criterion) +{ let a = vec![1; ZIPSZ]; let b = vec![1; ZIPSZ]; - let c = vec![1; ZIPSZ]; - bench.iter(|| { - a.iter() - .zip(b.iter()) - .zip(&c) - .fold(0, |acc, ((&a, &b), &c)| acc + a + b + c) + let c_vec = vec![1; ZIPSZ]; + c.bench_function("sum_3_std_zip2", |bn| { + bn.iter(|| { + a.iter() + .zip(b.iter()) + .zip(&c_vec) + .fold(0, |acc, ((&a, &b), &c)| acc + a + b + c) + }) }); } -#[bench] -fn sum_3_std_zip3(bench: &mut Bencher) { +fn sum_3_std_zip3(c: &mut Criterion) +{ let a = vec![1; ZIPSZ]; let b = vec![1; ZIPSZ]; - let c = vec![1; ZIPSZ]; - bench.iter(|| { - let mut s = 0; - for ((&a, &b), &c) in a.iter().zip(b.iter()).zip(&c) { - s += a + b + c - } - s + let c_vec = vec![1; ZIPSZ]; + c.bench_function("sum_3_std_zip3", |bn| { + bn.iter(|| { + let mut s = 0; + for ((&a, &b), &c) in a.iter().zip(b.iter()).zip(&c_vec) { + s += a + b + c + } + s + }) }); } -#[bench] -fn vector_sum_3_std_zip(bench: &mut Bencher) { +fn vector_sum_3_std_zip(c: &mut Criterion) +{ let a = vec![1.; ZIPSZ]; let b = vec![1.; ZIPSZ]; - let mut c = vec![1.; ZIPSZ]; - bench.iter(|| { - for ((&a, &b), c) in a.iter().zip(b.iter()).zip(&mut c) { - *c += a + b; - } + let mut c_vec = vec![1.; ZIPSZ]; + c.bench_function("vector_sum_3_std_zip", |bn| { + bn.iter(|| { + for ((&a, &b), c) in a.iter().zip(b.iter()).zip(&mut c_vec) { + *c += a + b; + } + }) }); } -#[bench] -fn sum_3_azip(bench: &mut Bencher) { +fn sum_3_azip(c: &mut Criterion) +{ let a = vec![1; ZIPSZ]; let b = vec![1; ZIPSZ]; - let c = vec![1; ZIPSZ]; - bench.iter(|| { - let mut s = 0; - azip!((&a in &a, &b in &b, &c in &c) { - s += a + b + c; - }); - s + let c_vec = vec![1; ZIPSZ]; + c.bench_function("sum_3_azip", |bn| { + bn.iter(|| { + let mut s = 0; + azip!((&a in &a, &b in &b, &c in &c_vec) { + s += a + b + c; + }); + s + }) }); } -#[bench] -fn sum_3_azip_fold(bench: &mut Bencher) { +fn sum_3_azip_fold(c: &mut Criterion) +{ let a = vec![1; ZIPSZ]; let b = vec![1; ZIPSZ]; - let c = vec![1; ZIPSZ]; - bench.iter(|| { - Zip::from(&a) - .and(&b) - .and(&c) - .fold_while(0, |acc, &a, &b, &c| FoldWhile::Continue(acc + a + b + c)) - .into_inner() + let c_vec = vec![1; ZIPSZ]; + c.bench_function("sum_3_azip_fold", |bn| { + bn.iter(|| { + Zip::from(&a) + .and(&b) + .and(&c_vec) + .fold_while(0, |acc, &a, &b, &c| FoldWhile::Continue(acc + a + b + c)) + .into_inner() + }) }); } -#[bench] -fn vector_sum_3_azip(bench: &mut Bencher) { +fn vector_sum_3_azip(c: &mut Criterion) +{ let a = vec![1.; ZIPSZ]; let b = vec![1.; ZIPSZ]; - let mut c = vec![1.; ZIPSZ]; - bench.iter(|| { - azip!((&a in &a, &b in &b, c in &mut c) { - *c += a + b; - }); + let mut c_vec = vec![1.; ZIPSZ]; + c.bench_function("vector_sum_3_azip", |bn| { + bn.iter(|| { + azip!((&a in &a, &b in &b, c in &mut c_vec) { + *c += a + b; + }); + }) }); } -fn vector_sum3_unchecked(a: &[f64], b: &[f64], c: &mut [f64]) { +fn vector_sum3_unchecked(a: &[f64], b: &[f64], c: &mut [f64]) +{ for i in 0..c.len() { unsafe { *c.get_unchecked_mut(i) += *a.get_unchecked(i) + *b.get_unchecked(i); @@ -205,29 +233,33 @@ fn vector_sum3_unchecked(a: &[f64], b: &[f64], c: &mut [f64]) { } } -#[bench] -fn vector_sum_3_zip_unchecked(bench: &mut Bencher) { +fn vector_sum_3_zip_unchecked(c: &mut Criterion) +{ let a = vec![1.; ZIPSZ]; let b = vec![1.; ZIPSZ]; - let mut c = vec![1.; ZIPSZ]; - bench.iter(move || { - vector_sum3_unchecked(&a, &b, &mut c); + let mut c_vec = vec![1.; ZIPSZ]; + c.bench_function("vector_sum_3_zip_unchecked", |bn| { + bn.iter(|| { + vector_sum3_unchecked(&a, &b, &mut c_vec); + }) }); } -#[bench] -fn vector_sum_3_zip_unchecked_manual(bench: &mut Bencher) { +fn vector_sum_3_zip_unchecked_manual(c: &mut Criterion) +{ let a = vec![1.; ZIPSZ]; let b = vec![1.; ZIPSZ]; - let mut c = vec![1.; ZIPSZ]; - bench.iter(move || unsafe { - let mut ap = a.as_ptr(); - let mut bp = b.as_ptr(); - let mut cp = c.as_mut_ptr(); - let cend = cp.add(c.len()); - while cp != cend { - *cp.post_inc() += *ap.post_inc() + *bp.post_inc(); - } + let mut c_vec = vec![1.; ZIPSZ]; + c.bench_function("vector_sum_3_zip_unchecked_manual", |bn| { + bn.iter(|| unsafe { + let mut ap = a.as_ptr(); + let mut bp = b.as_ptr(); + let mut cp = c_vec.as_mut_ptr(); + let cend = cp.add(c_vec.len()); + while cp != cend { + *cp.post_inc() += *ap.post_inc() + *bp.post_inc(); + } + }) }); } @@ -235,167 +267,232 @@ fn vector_sum_3_zip_unchecked_manual(bench: &mut Bencher) { const ISZ: usize = 16; const I2DSZ: usize = 64; -#[bench] -fn indexed_iter_1d_ix1(bench: &mut Bencher) { +fn indexed_iter_1d_ix1(c: &mut Criterion) +{ let mut a = Array::::zeros(I2DSZ * I2DSZ); for (i, elt) in a.indexed_iter_mut() { *elt = i as _; } - bench.iter(|| { - for (i, &_elt) in a.indexed_iter() { - //assert!(a[i] == elt); - black_box(i); - } - }) + c.bench_function("indexed_iter_1d_ix1", |bn| { + bn.iter(|| { + for (i, &_elt) in a.indexed_iter() { + black_box(i); + } + }) + }); } -#[bench] -fn indexed_zip_1d_ix1(bench: &mut Bencher) { +fn indexed_zip_1d_ix1(c: &mut Criterion) +{ let mut a = Array::::zeros(I2DSZ * I2DSZ); for (i, elt) in a.indexed_iter_mut() { *elt = i as _; } - bench.iter(|| { - Zip::indexed(&a).for_each(|i, &_elt| { - black_box(i); - //assert!(a[i] == elt); - }); - }) + c.bench_function("indexed_zip_1d_ix1", |bn| { + bn.iter(|| { + Zip::indexed(&a).for_each(|i, &_elt| { + black_box(i); + }); + }) + }); } -#[bench] -fn indexed_iter_2d_ix2(bench: &mut Bencher) { +fn indexed_iter_2d_ix2(c: &mut Criterion) +{ let mut a = Array::::zeros((I2DSZ, I2DSZ)); for ((i, j), elt) in a.indexed_iter_mut() { *elt = (i + 100 * j) as _; } - bench.iter(|| { - for (i, &_elt) in a.indexed_iter() { - //assert!(a[i] == elt); - black_box(i); - } - }) + c.bench_function("indexed_iter_2d_ix2", |bn| { + bn.iter(|| { + for (i, &_elt) in a.indexed_iter() { + black_box(i); + } + }) + }); } -#[bench] -fn indexed_zip_2d_ix2(bench: &mut Bencher) { + +fn indexed_zip_2d_ix2(c: &mut Criterion) +{ let mut a = Array::::zeros((I2DSZ, I2DSZ)); for ((i, j), elt) in a.indexed_iter_mut() { *elt = (i + 100 * j) as _; } - bench.iter(|| { - Zip::indexed(&a).for_each(|i, &_elt| { - black_box(i); - //assert!(a[i] == elt); - }); - }) + c.bench_function("indexed_zip_2d_ix2", |bn| { + bn.iter(|| { + Zip::indexed(&a).for_each(|i, &_elt| { + black_box(i); + }); + }) + }); } -#[bench] -fn indexed_iter_3d_ix3(bench: &mut Bencher) { +fn indexed_iter_3d_ix3(c: &mut Criterion) +{ let mut a = Array::::zeros((ISZ, ISZ, ISZ)); for ((i, j, k), elt) in a.indexed_iter_mut() { *elt = (i + 100 * j + 10000 * k) as _; } - bench.iter(|| { - for (i, &_elt) in a.indexed_iter() { - //assert!(a[i] == elt); - black_box(i); - } - }) + c.bench_function("indexed_iter_3d_ix3", |bn| { + bn.iter(|| { + for (i, &_elt) in a.indexed_iter() { + black_box(i); + } + }) + }); } -#[bench] -fn indexed_zip_3d_ix3(bench: &mut Bencher) { +fn indexed_zip_3d_ix3(c: &mut Criterion) +{ let mut a = Array::::zeros((ISZ, ISZ, ISZ)); for ((i, j, k), elt) in a.indexed_iter_mut() { *elt = (i + 100 * j + 10000 * k) as _; } - bench.iter(|| { - Zip::indexed(&a).for_each(|i, &_elt| { - black_box(i); - //assert!(a[i] == elt); - }); - }) + c.bench_function("indexed_zip_3d_ix3", |bn| { + bn.iter(|| { + Zip::indexed(&a).for_each(|i, &_elt| { + black_box(i); + }); + }) + }); } -#[bench] -fn indexed_iter_3d_dyn(bench: &mut Bencher) { +fn indexed_iter_3d_dyn(c: &mut Criterion) +{ let mut a = Array::::zeros((ISZ, ISZ, ISZ)); for ((i, j, k), elt) in a.indexed_iter_mut() { *elt = (i + 100 * j + 10000 * k) as _; } let a = a.into_shape_with_order(&[ISZ; 3][..]).unwrap(); - bench.iter(|| { - for (i, &_elt) in a.indexed_iter() { - //assert!(a[i] == elt); - black_box(i); - } - }) + c.bench_function("indexed_iter_3d_dyn", |bn| { + bn.iter(|| { + for (i, &_elt) in a.indexed_iter() { + black_box(i); + } + }) + }); } -#[bench] -fn iter_sum_1d_strided_fold(bench: &mut Bencher) { +fn iter_sum_1d_strided_fold(c: &mut Criterion) +{ let mut a = Array::::ones(10240); a.slice_axis_inplace(Axis(0), Slice::new(0, None, 2)); - bench.iter(|| a.iter().sum::()); + c.bench_function("iter_sum_1d_strided_fold", |bn| bn.iter(|| a.iter().sum::())); } -#[bench] -fn iter_sum_1d_strided_rfold(bench: &mut Bencher) { +fn iter_sum_1d_strided_rfold(c: &mut Criterion) +{ let mut a = Array::::ones(10240); a.slice_axis_inplace(Axis(0), Slice::new(0, None, 2)); - bench.iter(|| a.iter().rfold(0, |acc, &x| acc + x)); + c.bench_function("iter_sum_1d_strided_rfold", |bn| { + bn.iter(|| a.iter().rfold(0, |acc, &x| acc + x)) + }); } -#[bench] -fn iter_axis_iter_sum(bench: &mut Bencher) { +fn iter_axis_iter_sum(c: &mut Criterion) +{ let a = Array::::zeros((64, 64)); - bench.iter(|| a.axis_iter(Axis(0)).map(|plane| plane.sum()).sum::()); + c.bench_function("iter_axis_iter_sum", |bn| { + bn.iter(|| a.axis_iter(Axis(0)).map(|plane| plane.sum()).sum::()) + }); } -#[bench] -fn iter_axis_chunks_1_iter_sum(bench: &mut Bencher) { +fn iter_axis_chunks_1_iter_sum(c: &mut Criterion) +{ let a = Array::::zeros((64, 64)); - bench.iter(|| { - a.axis_chunks_iter(Axis(0), 1) - .map(|plane| plane.sum()) - .sum::() + c.bench_function("iter_axis_chunks_1_iter_sum", |bn| { + bn.iter(|| { + a.axis_chunks_iter(Axis(0), 1) + .map(|plane| plane.sum()) + .sum::() + }) }); } -#[bench] -fn iter_axis_chunks_5_iter_sum(bench: &mut Bencher) { +fn iter_axis_chunks_5_iter_sum(c: &mut Criterion) +{ let a = Array::::zeros((64, 64)); - bench.iter(|| { - a.axis_chunks_iter(Axis(0), 5) - .map(|plane| plane.sum()) - .sum::() + c.bench_function("iter_axis_chunks_5_iter_sum", |bn| { + bn.iter(|| { + a.axis_chunks_iter(Axis(0), 5) + .map(|plane| plane.sum()) + .sum::() + }) }); } -pub fn zip_mut_with(data: &Array3, out: &mut Array3) { +pub fn zip_mut_with(data: &Array3, out: &mut Array3) +{ out.zip_mut_with(data, |o, &i| { *o = i; }); } -#[bench] -fn zip_mut_with_cc(b: &mut Bencher) { +fn zip_mut_with_cc(c: &mut Criterion) +{ let data: Array3 = Array3::zeros((ISZ, ISZ, ISZ)); let mut out = Array3::zeros(data.dim()); - b.iter(|| zip_mut_with(&data, &mut out)); + c.bench_function("zip_mut_with_cc", |b| b.iter(|| zip_mut_with(&data, &mut out))); } -#[bench] -fn zip_mut_with_ff(b: &mut Bencher) { +fn zip_mut_with_ff(c: &mut Criterion) +{ let data: Array3 = Array3::zeros((ISZ, ISZ, ISZ).f()); let mut out = Array3::zeros(data.dim().f()); - b.iter(|| zip_mut_with(&data, &mut out)); + c.bench_function("zip_mut_with_ff", |b| b.iter(|| zip_mut_with(&data, &mut out))); } + +#[cfg(feature = "std")] +criterion_group!( + benches_std, + iter_filter_sum_2d_u32, + iter_filter_sum_2d_f32, + iter_filter_sum_2d_stride_u32, + iter_filter_sum_2d_stride_f32, + iter_rev_step_by_contiguous, + iter_rev_step_by_discontiguous, +); + +criterion_group!( + benches, + iter_sum_2d_regular, + iter_sum_2d_cutout, + iter_all_2d_cutout, + iter_sum_2d_transpose, + sum_3_std_zip1, + sum_3_std_zip2, + sum_3_std_zip3, + vector_sum_3_std_zip, + sum_3_azip, + sum_3_azip_fold, + vector_sum_3_azip, + vector_sum_3_zip_unchecked, + vector_sum_3_zip_unchecked_manual, + indexed_iter_1d_ix1, + indexed_zip_1d_ix1, + indexed_iter_2d_ix2, + indexed_zip_2d_ix2, + indexed_iter_3d_ix3, + indexed_zip_3d_ix3, + indexed_iter_3d_dyn, + iter_sum_1d_strided_fold, + iter_sum_1d_strided_rfold, + iter_axis_iter_sum, + iter_axis_chunks_1_iter_sum, + iter_axis_chunks_5_iter_sum, + zip_mut_with_cc, + zip_mut_with_ff, +); + +#[cfg(feature = "std")] +criterion_main!(benches, benches_std); + +#[cfg(not(feature = "std"))] +criterion_main!(benches); diff --git a/benches/numeric.rs b/benches/numeric.rs index ea6e58e6..46fcace0 100644 --- a/benches/numeric.rs +++ b/benches/numeric.rs @@ -1,8 +1,4 @@ -#![feature(test)] - -extern crate test; -use test::Bencher; - +use criterion::{black_box, criterion_group, criterion_main, Criterion}; use ndarray::prelude::*; const N: usize = 1024; @@ -10,22 +6,29 @@ const X: usize = 64; const Y: usize = 16; #[cfg(feature = "std")] -#[bench] -fn clip(bench: &mut Bencher) { +fn clip(c: &mut Criterion) { let mut a = Array::linspace(0.0..=127.0, N * 2) .into_shape_with_order([X, Y * 2]) .unwrap(); let min = 2.; let max = 5.; - bench.iter(|| { - a.mapv_inplace(|mut x| { - if x < min { - x = min - } - if x > max { - x = max - } - x + c.bench_function("clip", |b| { + b.iter(|| { + black_box(&mut a).mapv_inplace(|mut x| { + if x < min { + x = min + } + if x > max { + x = max + } + x + }) }) }); } + +#[cfg(feature = "std")] +criterion_group!(benches, clip); +#[cfg(not(feature = "std"))] +criterion_group!(benches,); +criterion_main!(benches); diff --git a/benches/par_rayon.rs b/benches/par_rayon.rs index 393bc215..857660ee 100644 --- a/benches/par_rayon.rs +++ b/benches/par_rayon.rs @@ -1,138 +1,154 @@ #![cfg(feature = "rayon")] -#![feature(test)] +use criterion::{criterion_group, criterion_main, Criterion}; use ndarray::parallel::prelude::*; use ndarray::prelude::*; - -extern crate test; -use test::Bencher; - use ndarray::Zip; const EXP_N: usize = 256; const ADDN: usize = 512; -fn set_threads() { +fn set_threads() +{ // Consider setting a fixed number of threads here, for example to avoid // oversubscribing on hyperthreaded cores. // let n = 4; // let _ = rayon::ThreadPoolBuilder::new().num_threads(n).build_global(); } -#[bench] -fn map_exp_regular(bench: &mut Bencher) { +fn map_exp_regular(c: &mut Criterion) +{ let mut a = Array2::::zeros((EXP_N, EXP_N)); a.swap_axes(0, 1); - bench.iter(|| { - a.mapv_inplace(|x| x.exp()); + c.bench_function("map_exp_regular", |b| { + b.iter(|| { + a.mapv_inplace(|x| x.exp()); + }); }); } -#[bench] -fn rayon_exp_regular(bench: &mut Bencher) { +fn rayon_exp_regular(c: &mut Criterion) +{ set_threads(); let mut a = Array2::::zeros((EXP_N, EXP_N)); a.swap_axes(0, 1); - bench.iter(|| { - a.view_mut().into_par_iter().for_each(|x| *x = x.exp()); + c.bench_function("rayon_exp_regular", |b| { + b.iter(|| { + a.view_mut().into_par_iter().for_each(|x| *x = x.exp()); + }); }); } const FASTEXP: usize = EXP_N; #[inline] -fn fastexp(x: f64) -> f64 { +fn fastexp(x: f64) -> f64 +{ let x = 1. + x / 1024.; x.powi(1024) } -#[bench] -fn map_fastexp_regular(bench: &mut Bencher) { +fn map_fastexp_regular(c: &mut Criterion) +{ let mut a = Array2::::zeros((FASTEXP, FASTEXP)); - bench.iter(|| a.mapv_inplace(fastexp)); + c.bench_function("map_fastexp_regular", |b| b.iter(|| a.mapv_inplace(fastexp))); } -#[bench] -fn rayon_fastexp_regular(bench: &mut Bencher) { +fn rayon_fastexp_regular(c: &mut Criterion) +{ set_threads(); let mut a = Array2::::zeros((FASTEXP, FASTEXP)); - bench.iter(|| { - a.view_mut().into_par_iter().for_each(|x| *x = fastexp(*x)); + c.bench_function("rayon_fastexp_regular", |b| { + b.iter(|| { + a.view_mut().into_par_iter().for_each(|x| *x = fastexp(*x)); + }); }); } -#[bench] -fn map_fastexp_cut(bench: &mut Bencher) { +fn map_fastexp_cut(c: &mut Criterion) +{ let mut a = Array2::::zeros((FASTEXP, FASTEXP)); let mut a = a.slice_mut(s![.., ..-1]); - bench.iter(|| a.mapv_inplace(fastexp)); + c.bench_function("map_fastexp_cut", |b| b.iter(|| a.mapv_inplace(fastexp))); } -#[bench] -fn rayon_fastexp_cut(bench: &mut Bencher) { +fn rayon_fastexp_cut(c: &mut Criterion) +{ set_threads(); let mut a = Array2::::zeros((FASTEXP, FASTEXP)); let mut a = a.slice_mut(s![.., ..-1]); - bench.iter(|| { - a.view_mut().into_par_iter().for_each(|x| *x = fastexp(*x)); + c.bench_function("rayon_fastexp_cut", |b| { + b.iter(|| { + a.view_mut().into_par_iter().for_each(|x| *x = fastexp(*x)); + }); }); } -#[bench] -fn map_fastexp_by_axis(bench: &mut Bencher) { +fn map_fastexp_by_axis(c: &mut Criterion) +{ let mut a = Array2::::zeros((FASTEXP, FASTEXP)); - bench.iter(|| { - for mut sheet in a.axis_iter_mut(Axis(0)) { - sheet.mapv_inplace(fastexp) - } + c.bench_function("map_fastexp_by_axis", |b| { + b.iter(|| { + for mut sheet in a.axis_iter_mut(Axis(0)) { + sheet.mapv_inplace(fastexp) + } + }); }); } -#[bench] -fn rayon_fastexp_by_axis(bench: &mut Bencher) { +fn rayon_fastexp_by_axis(c: &mut Criterion) +{ set_threads(); let mut a = Array2::::zeros((FASTEXP, FASTEXP)); - bench.iter(|| { - a.axis_iter_mut(Axis(0)) - .into_par_iter() - .for_each(|mut sheet| sheet.mapv_inplace(fastexp)); + c.bench_function("rayon_fastexp_by_axis", |b| { + b.iter(|| { + a.axis_iter_mut(Axis(0)) + .into_par_iter() + .for_each(|mut sheet| sheet.mapv_inplace(fastexp)); + }); }); } -#[bench] -fn rayon_fastexp_zip(bench: &mut Bencher) { +fn rayon_fastexp_zip(c: &mut Criterion) +{ set_threads(); let mut a = Array2::::zeros((FASTEXP, FASTEXP)); - bench.iter(|| { - Zip::from(&mut a) - .into_par_iter() - .for_each(|(elt,)| *elt = fastexp(*elt)); + c.bench_function("rayon_fastexp_zip", |b| { + b.iter(|| { + Zip::from(&mut a) + .into_par_iter() + .for_each(|(elt,)| *elt = fastexp(*elt)); + }); }); } -#[bench] -fn add(bench: &mut Bencher) { +fn add(c: &mut Criterion) +{ let mut a = Array2::::zeros((ADDN, ADDN)); - let b = Array2::::zeros((ADDN, ADDN)); - let c = Array2::::zeros((ADDN, ADDN)); + let b_arr = Array2::::zeros((ADDN, ADDN)); + let c_arr = Array2::::zeros((ADDN, ADDN)); let d = Array2::::zeros((ADDN, ADDN)); - bench.iter(|| { - azip!((a in &mut a, &b in &b, &c in &c, &d in &d) { - *a += b.exp() + c.exp() + d.exp(); + c.bench_function("add", |bench| { + bench.iter(|| { + azip!((a in &mut a, &b in &b_arr, &c in &c_arr, &d in &d) { + *a += b.exp() + c.exp() + d.exp(); + }); }); }); } -#[bench] -fn rayon_add(bench: &mut Bencher) { +fn rayon_add(c: &mut Criterion) +{ set_threads(); let mut a = Array2::::zeros((ADDN, ADDN)); - let b = Array2::::zeros((ADDN, ADDN)); - let c = Array2::::zeros((ADDN, ADDN)); + let b_arr = Array2::::zeros((ADDN, ADDN)); + let c_arr = Array2::::zeros((ADDN, ADDN)); let d = Array2::::zeros((ADDN, ADDN)); - bench.iter(|| { - par_azip!((a in &mut a, b in &b, c in &c, d in &d) { - *a += b.exp() + c.exp() + d.exp(); + c.bench_function("rayon_add", |bench| { + bench.iter(|| { + par_azip!((a in &mut a, b in &b_arr, c in &c_arr, d in &d) { + *a += b.exp() + c.exp() + d.exp(); + }); }); }); } @@ -140,26 +156,54 @@ fn rayon_add(bench: &mut Bencher) { const COLL_STRING_N: usize = 64; const COLL_F64_N: usize = 128; -#[bench] -fn vec_string_collect(bench: &mut test::Bencher) { +fn vec_string_collect(c: &mut Criterion) +{ let v = vec![""; COLL_STRING_N * COLL_STRING_N]; - bench.iter(|| v.iter().map(|s| s.to_owned()).collect::>()); + c.bench_function("vec_string_collect", |b| { + b.iter(|| v.iter().map(|s| s.to_owned()).collect::>()); + }); } -#[bench] -fn array_string_collect(bench: &mut test::Bencher) { +fn array_string_collect(c: &mut Criterion) +{ let v = Array::from_elem((COLL_STRING_N, COLL_STRING_N), ""); - bench.iter(|| Zip::from(&v).par_map_collect(|s| s.to_owned())); + c.bench_function("array_string_collect", |b| { + b.iter(|| Zip::from(&v).par_map_collect(|s| s.to_owned())); + }); } -#[bench] -fn vec_f64_collect(bench: &mut test::Bencher) { +fn vec_f64_collect(c: &mut Criterion) +{ let v = vec![1.; COLL_F64_N * COLL_F64_N]; - bench.iter(|| v.iter().map(|s| s + 1.).collect::>()); + c.bench_function("vec_f64_collect", |b| { + b.iter(|| v.iter().map(|s| s + 1.).collect::>()); + }); } -#[bench] -fn array_f64_collect(bench: &mut test::Bencher) { +fn array_f64_collect(c: &mut Criterion) +{ let v = Array::from_elem((COLL_F64_N, COLL_F64_N), 1.); - bench.iter(|| Zip::from(&v).par_map_collect(|s| s + 1.)); + c.bench_function("array_f64_collect", |b| { + b.iter(|| Zip::from(&v).par_map_collect(|s| s + 1.)); + }); } + +criterion_group!( + benches, + map_exp_regular, + rayon_exp_regular, + map_fastexp_regular, + rayon_fastexp_regular, + map_fastexp_cut, + rayon_fastexp_cut, + map_fastexp_by_axis, + rayon_fastexp_by_axis, + rayon_fastexp_zip, + add, + rayon_add, + vec_string_collect, + array_string_collect, + vec_f64_collect, + array_f64_collect +); +criterion_main!(benches); diff --git a/benches/reserve.rs b/benches/reserve.rs index 422d1283..791bbefa 100644 --- a/benches/reserve.rs +++ b/benches/reserve.rs @@ -1,29 +1,32 @@ -#![feature(test)] - -extern crate test; -use test::Bencher; - +use criterion::{criterion_group, criterion_main, Criterion}; use ndarray::prelude::*; -#[bench] -fn push_reserve(bench: &mut Bencher) { +fn push_reserve(c: &mut Criterion) +{ let ones: Array = array![1f32]; - bench.iter(|| { - let mut a: Array = array![]; - a.reserve(Axis(0), 100).unwrap(); - for _ in 0..100 { - a.append(Axis(0), ones.view()).unwrap(); - } + c.bench_function("push_reserve", |b| { + b.iter(|| { + let mut a: Array = array![]; + a.reserve(Axis(0), 100).unwrap(); + for _ in 0..100 { + a.append(Axis(0), ones.view()).unwrap(); + } + }); }); } -#[bench] -fn push_no_reserve(bench: &mut Bencher) { +fn push_no_reserve(c: &mut Criterion) +{ let ones: Array = array![1f32]; - bench.iter(|| { - let mut a: Array = array![]; - for _ in 0..100 { - a.append(Axis(0), ones.view()).unwrap(); - } + c.bench_function("push_no_reserve", |b| { + b.iter(|| { + let mut a: Array = array![]; + for _ in 0..100 { + a.append(Axis(0), ones.view()).unwrap(); + } + }); }); } + +criterion_group!(benches, push_reserve, push_no_reserve); +criterion_main!(benches); diff --git a/benches/to_shape.rs b/benches/to_shape.rs index 7c9f9144..fcf2d927 100644 --- a/benches/to_shape.rs +++ b/benches/to_shape.rs @@ -1,84 +1,118 @@ -#![feature(test)] - -extern crate test; -use test::Bencher; - +use criterion::{criterion_group, criterion_main, Criterion}; use ndarray::prelude::*; use ndarray::Order; -#[bench] -fn to_shape2_1(bench: &mut Bencher) { +fn to_shape2_1(c: &mut Criterion) +{ let a = Array::::zeros((4, 5)); let view = a.view(); - bench.iter(|| view.to_shape(4 * 5).unwrap()); + c.bench_function("to_shape2_1", |b| { + b.iter(|| view.to_shape(4 * 5).unwrap()); + }); } -#[bench] -fn to_shape2_2_same(bench: &mut Bencher) { +fn to_shape2_2_same(c: &mut Criterion) +{ let a = Array::::zeros((4, 5)); let view = a.view(); - bench.iter(|| view.to_shape((4, 5)).unwrap()); + c.bench_function("to_shape2_2_same", |b| { + b.iter(|| view.to_shape((4, 5)).unwrap()); + }); } -#[bench] -fn to_shape2_2_flip(bench: &mut Bencher) { +fn to_shape2_2_flip(c: &mut Criterion) +{ let a = Array::::zeros((4, 5)); let view = a.view(); - bench.iter(|| view.to_shape((5, 4)).unwrap()); + c.bench_function("to_shape2_2_flip", |b| { + b.iter(|| view.to_shape((5, 4)).unwrap()); + }); } -#[bench] -fn to_shape2_3(bench: &mut Bencher) { +fn to_shape2_3(c: &mut Criterion) +{ let a = Array::::zeros((4, 5)); let view = a.view(); - bench.iter(|| view.to_shape((2, 5, 2)).unwrap()); + c.bench_function("to_shape2_3", |b| { + b.iter(|| view.to_shape((2, 5, 2)).unwrap()); + }); } -#[bench] -fn to_shape3_1(bench: &mut Bencher) { +fn to_shape3_1(c: &mut Criterion) +{ let a = Array::::zeros((3, 4, 5)); let view = a.view(); - bench.iter(|| view.to_shape(3 * 4 * 5).unwrap()); + c.bench_function("to_shape3_1", |b| { + b.iter(|| view.to_shape(3 * 4 * 5).unwrap()); + }); } -#[bench] -fn to_shape3_2_order(bench: &mut Bencher) { +fn to_shape3_2_order(c: &mut Criterion) +{ let a = Array::::zeros((3, 4, 5)); let view = a.view(); - bench.iter(|| view.to_shape((12, 5)).unwrap()); + c.bench_function("to_shape3_2_order", |b| { + b.iter(|| view.to_shape((12, 5)).unwrap()); + }); } -#[bench] -fn to_shape3_2_outoforder(bench: &mut Bencher) { +fn to_shape3_2_outoforder(c: &mut Criterion) +{ let a = Array::::zeros((3, 4, 5)); let view = a.view(); - bench.iter(|| view.to_shape((4, 15)).unwrap()); + c.bench_function("to_shape3_2_outoforder", |b| { + b.iter(|| view.to_shape((4, 15)).unwrap()); + }); } -#[bench] -fn to_shape3_3c(bench: &mut Bencher) { +fn to_shape3_3c(c: &mut Criterion) +{ let a = Array::::zeros((3, 4, 5)); let view = a.view(); - bench.iter(|| view.to_shape((3, 4, 5)).unwrap()); + c.bench_function("to_shape3_3c", |b| { + b.iter(|| view.to_shape((3, 4, 5)).unwrap()); + }); } -#[bench] -fn to_shape3_3f(bench: &mut Bencher) { +fn to_shape3_3f(c: &mut Criterion) +{ let a = Array::::zeros((3, 4, 5).f()); let view = a.view(); - bench.iter(|| view.to_shape(((3, 4, 5), Order::F)).unwrap()); + c.bench_function("to_shape3_3f", |b| { + b.iter(|| view.to_shape(((3, 4, 5), Order::F)).unwrap()); + }); } -#[bench] -fn to_shape3_4c(bench: &mut Bencher) { +fn to_shape3_4c(c: &mut Criterion) +{ let a = Array::::zeros((3, 4, 5)); let view = a.view(); - bench.iter(|| view.to_shape(((2, 3, 2, 5), Order::C)).unwrap()); + c.bench_function("to_shape3_4c", |b| { + b.iter(|| view.to_shape(((2, 3, 2, 5), Order::C)).unwrap()); + }); } -#[bench] -fn to_shape3_4f(bench: &mut Bencher) { +fn to_shape3_4f(c: &mut Criterion) +{ let a = Array::::zeros((3, 4, 5).f()); let view = a.view(); - bench.iter(|| view.to_shape(((2, 3, 2, 5), Order::F)).unwrap()); + c.bench_function("to_shape3_4f", |b| { + b.iter(|| view.to_shape(((2, 3, 2, 5), Order::F)).unwrap()); + }); } + +criterion_group!( + benches, + to_shape2_1, + to_shape2_2_same, + to_shape2_2_flip, + to_shape2_3, + to_shape3_1, + to_shape3_2_order, + to_shape3_2_outoforder, + to_shape3_3c, + to_shape3_3f, + to_shape3_4c, + to_shape3_4f +); +criterion_main!(benches); diff --git a/benches/zip.rs b/benches/zip.rs index 1194e450..66246842 100644 --- a/benches/zip.rs +++ b/benches/zip.rs @@ -1,9 +1,7 @@ -#![feature(test)] -extern crate test; +use criterion::{black_box, criterion_group, criterion_main, Criterion}; use ndarray::s; use ndarray::IntoNdProducer; use ndarray::{Array3, ShapeBuilder, Zip}; -use test::{black_box, Bencher}; pub fn zip_copy<'a, A, P, Q>(data: P, out: Q) where @@ -33,7 +31,8 @@ where z22.for_each(f); } -pub fn zip_indexed(data: &Array3, out: &mut Array3) { +pub fn zip_indexed(data: &Array3, out: &mut Array3) +{ Zip::indexed(data).and(out).for_each(|idx, &i, o| { let _ = black_box(idx); *o = i; @@ -43,80 +42,95 @@ pub fn zip_indexed(data: &Array3, out: &mut Array3) { // array size in benchmarks const SZ3: (usize, usize, usize) = (100, 110, 100); -#[bench] -fn zip_cc(b: &mut Bencher) { +fn zip_cc(c: &mut Criterion) +{ let data: Array3 = Array3::zeros(SZ3); let mut out = Array3::zeros(data.dim()); - b.iter(|| zip_copy(&data, &mut out)); + c.bench_function("zip_cc", |b| b.iter(|| zip_copy(&data, &mut out))); } -#[bench] -fn zip_cf(b: &mut Bencher) { +fn zip_cf(c: &mut Criterion) +{ let data: Array3 = Array3::zeros(SZ3); let mut out = Array3::zeros(data.dim().f()); - b.iter(|| zip_copy(&data, &mut out)); + c.bench_function("zip_cf", |b| b.iter(|| zip_copy(&data, &mut out))); } -#[bench] -fn zip_fc(b: &mut Bencher) { +fn zip_fc(c: &mut Criterion) +{ let data: Array3 = Array3::zeros(SZ3.f()); let mut out = Array3::zeros(data.dim()); - b.iter(|| zip_copy(&data, &mut out)); + c.bench_function("zip_fc", |b| b.iter(|| zip_copy(&data, &mut out))); } -#[bench] -fn zip_ff(b: &mut Bencher) { +fn zip_ff(c: &mut Criterion) +{ let data: Array3 = Array3::zeros(SZ3.f()); let mut out = Array3::zeros(data.dim().f()); - b.iter(|| zip_copy(&data, &mut out)); + c.bench_function("zip_ff", |b| b.iter(|| zip_copy(&data, &mut out))); } -#[bench] -fn zip_indexed_cc(b: &mut Bencher) { +fn zip_indexed_cc(c: &mut Criterion) +{ let data: Array3 = Array3::zeros(SZ3); let mut out = Array3::zeros(data.dim()); - b.iter(|| zip_indexed(&data, &mut out)); + c.bench_function("zip_indexed_cc", |b| b.iter(|| zip_indexed(&data, &mut out))); } -#[bench] -fn zip_indexed_ff(b: &mut Bencher) { +fn zip_indexed_ff(c: &mut Criterion) +{ let data: Array3 = Array3::zeros(SZ3.f()); let mut out = Array3::zeros(data.dim().f()); - b.iter(|| zip_indexed(&data, &mut out)); + c.bench_function("zip_indexed_ff", |b| b.iter(|| zip_indexed(&data, &mut out))); } -#[bench] -fn slice_zip_cc(b: &mut Bencher) { +fn slice_zip_cc(c: &mut Criterion) +{ let data: Array3 = Array3::zeros(SZ3); let mut out = Array3::zeros(data.dim()); let data = data.slice(s![1.., 1.., 1..]); let mut out = out.slice_mut(s![1.., 1.., 1..]); - b.iter(|| zip_copy(&data, &mut out)); + c.bench_function("slice_zip_cc", |b| b.iter(|| zip_copy(&data, &mut out))); } -#[bench] -fn slice_zip_ff(b: &mut Bencher) { +fn slice_zip_ff(c: &mut Criterion) +{ let data: Array3 = Array3::zeros(SZ3.f()); let mut out = Array3::zeros(data.dim().f()); let data = data.slice(s![1.., 1.., 1..]); let mut out = out.slice_mut(s![1.., 1.., 1..]); - b.iter(|| zip_copy(&data, &mut out)); + c.bench_function("slice_zip_ff", |b| b.iter(|| zip_copy(&data, &mut out))); } -#[bench] -fn slice_split_zip_cc(b: &mut Bencher) { +fn slice_split_zip_cc(c: &mut Criterion) +{ let data: Array3 = Array3::zeros(SZ3); let mut out = Array3::zeros(data.dim()); let data = data.slice(s![1.., 1.., 1..]); let mut out = out.slice_mut(s![1.., 1.., 1..]); - b.iter(|| zip_copy_split(&data, &mut out)); + c.bench_function("slice_split_zip_cc", |b| b.iter(|| zip_copy_split(&data, &mut out))); } -#[bench] -fn slice_split_zip_ff(b: &mut Bencher) { +fn slice_split_zip_ff(c: &mut Criterion) +{ let data: Array3 = Array3::zeros(SZ3.f()); let mut out = Array3::zeros(data.dim().f()); let data = data.slice(s![1.., 1.., 1..]); let mut out = out.slice_mut(s![1.., 1.., 1..]); - b.iter(|| zip_copy_split(&data, &mut out)); + c.bench_function("slice_split_zip_ff", |b| b.iter(|| zip_copy_split(&data, &mut out))); } + +criterion_group!( + benches, + zip_cc, + zip_cf, + zip_fc, + zip_ff, + zip_indexed_cc, + zip_indexed_ff, + slice_zip_cc, + slice_zip_ff, + slice_split_zip_cc, + slice_split_zip_ff +); +criterion_main!(benches); diff --git a/examples/life.rs b/examples/life.rs index d430858b..0c043190 100644 --- a/examples/life.rs +++ b/examples/life.rs @@ -1,4 +1,13 @@ -#![allow(clippy::many_single_char_names, clippy::deref_addrof, clippy::unreadable_literal)] +// `s![1..-1, 1..-1]` / `s![0..-2, 0..-2]` — ndarray's `s!` macro uses +// Python-style negative indexing. Clippy can't see through the macro and +// reads `1..-1` as a plain (empty) Rust range; the actual semantics are +// correct. +#![allow( + clippy::many_single_char_names, + clippy::deref_addrof, + clippy::unreadable_literal, + clippy::reversed_empty_ranges +)] use ndarray::prelude::*; diff --git a/ndarray-rand/Cargo.toml b/ndarray-rand/Cargo.toml index b7169f30..31037644 100644 --- a/ndarray-rand/Cargo.toml +++ b/ndarray-rand/Cargo.toml @@ -31,6 +31,11 @@ quickcheck = { workspace = true, optional = true } [dev-dependencies] rand_isaac = "0.4.0" quickcheck = { workspace = true } +criterion = { version = "0.5", features = ["html_reports"] } + +[[bench]] +name = "bench" +harness = false [package.metadata.release] tag-name = "ndarray-rand-{{version}}" diff --git a/ndarray-rand/benches/bench.rs b/ndarray-rand/benches/bench.rs index e28eb620..4d8e9370 100644 --- a/ndarray-rand/benches/bench.rs +++ b/ndarray-rand/benches/bench.rs @@ -1,28 +1,32 @@ -#![feature(test)] - -extern crate test; - +use criterion::{criterion_group, criterion_main, Criterion}; use ndarray::Array; use ndarray_rand::RandomExt; use rand_distr::Normal; use rand_distr::Uniform; -use test::Bencher; - -#[bench] -fn uniform_f32(b: &mut Bencher) { +fn uniform_f32(c: &mut Criterion) +{ let m = 100; - b.iter(|| Array::random((m, m), Uniform::new(-1f32, 1.).unwrap())); + c.bench_function("uniform_f32", |b| { + b.iter(|| Array::random((m, m), Uniform::new(-1f32, 1.).unwrap())); + }); } -#[bench] -fn norm_f32(b: &mut Bencher) { +fn norm_f32(c: &mut Criterion) +{ let m = 100; - b.iter(|| Array::random((m, m), Normal::new(0f32, 1.).unwrap())); + c.bench_function("norm_f32", |b| { + b.iter(|| Array::random((m, m), Normal::new(0f32, 1.).unwrap())); + }); } -#[bench] -fn norm_f64(b: &mut Bencher) { +fn norm_f64(c: &mut Criterion) +{ let m = 100; - b.iter(|| Array::random((m, m), Normal::new(0f64, 1.).unwrap())); + c.bench_function("norm_f64", |b| { + b.iter(|| Array::random((m, m), Normal::new(0f64, 1.).unwrap())); + }); } + +criterion_group!(benches, uniform_f32, norm_f32, norm_f64); +criterion_main!(benches); diff --git a/src/hpc/blackboard.rs b/src/hpc/blackboard.rs index 82b2ca15..471dd83d 100644 --- a/src/hpc/blackboard.rs +++ b/src/hpc/blackboard.rs @@ -461,8 +461,8 @@ mod tests { #[test] fn test_alloc_get_f32() { let mut bb = Blackboard::new(); - bb.alloc_f32("x", 3.14); - assert_eq!(bb.get_f32("x"), Some(&3.14)); + bb.alloc_f32("x", 2.5); + assert_eq!(bb.get_f32("x"), Some(&2.5)); assert_eq!(bb.get_f32("y"), None); } diff --git a/src/hpc/jitson/parser.rs b/src/hpc/jitson/parser.rs index 88334e23..80a061a3 100644 --- a/src/hpc/jitson/parser.rs +++ b/src/hpc/jitson/parser.rs @@ -461,10 +461,10 @@ mod tests { #[test] fn test_parse_negative_and_float() { - let input = r#"{"neg": -42, "flt": 3.14, "exp": 1e10}"#; + let input = r#"{"neg": -42, "flt": 2.5, "exp": 1e10}"#; let root = parse_json(input).unwrap(); assert!((root.get("neg").unwrap().as_f64().unwrap() - (-42.0)).abs() < 1e-10); - assert!((root.get("flt").unwrap().as_f64().unwrap() - 3.14).abs() < 1e-10); + assert!((root.get("flt").unwrap().as_f64().unwrap() - 2.5).abs() < 1e-10); assert!((root.get("exp").unwrap().as_f64().unwrap() - 1e10).abs() < 1.0); } diff --git a/src/hpc/quantized.rs b/src/hpc/quantized.rs index 50bf9432..2a98e214 100644 --- a/src/hpc/quantized.rs +++ b/src/hpc/quantized.rs @@ -887,7 +887,7 @@ mod tests { #[test] fn test_bf16_roundtrip() { - let values = [1.0f32, -1.0, 0.0, 3.14, 1000.0, 0.001]; + let values = [1.0f32, -1.0, 0.0, 2.5, 1000.0, 0.001]; for &v in &values { let bf = BF16::from_f32(v); let back = bf.to_f32(); diff --git a/tests/array.rs b/tests/array.rs index bab3563d..1c9e1fdd 100644 --- a/tests/array.rs +++ b/tests/array.rs @@ -1,4 +1,8 @@ #![allow(non_snake_case)] +// `s![1..-1, ..]` etc. — ndarray's `s!` macro uses Python-style negative +// indexing. Clippy can't see through the macro and reads `1..-1` as a plain +// (empty) Rust range; the actual semantics are correct. +#![allow(clippy::reversed_empty_ranges)] #![allow( clippy::many_single_char_names, clippy::deref_addrof, clippy::unreadable_literal, clippy::float_cmp )] diff --git a/tests/assign.rs b/tests/assign.rs index 8205828c..9ae7744c 100644 --- a/tests/assign.rs +++ b/tests/assign.rs @@ -1,3 +1,8 @@ +// `s![1..-1, ..;2]` — ndarray's `s!` macro uses Python-style negative +// indexing. Clippy can't see through the macro and reads `1..-1` as a +// plain (empty) Rust range; the actual semantics are correct. +#![allow(clippy::reversed_empty_ranges)] + use ndarray::prelude::*; use std::sync::atomic::{AtomicUsize, Ordering}; diff --git a/tests/oper.rs b/tests/oper.rs index c3da2d5d..17b1b096 100644 --- a/tests/oper.rs +++ b/tests/oper.rs @@ -1,4 +1,6 @@ #![allow(clippy::many_single_char_names, clippy::deref_addrof, clippy::unreadable_literal)] +use std::mem::MaybeUninit; + use ndarray::linalg::general_mat_mul; use ndarray::linalg::kron; use ndarray::prelude::*; @@ -287,16 +289,19 @@ where let ((m, k), (k2, n)) = (lhs.dim(), rhs.dim()); assert!(m.checked_mul(n).is_some()); assert_eq!(k, k2); - let mut res_elems = Vec::::with_capacity(m * n); - unsafe { - res_elems.set_len(m * n); - } + // SAFETY: We allocate `m * n` MaybeUninit slots, then write into every + // slot exactly once via the `for rr in &mut res_elems` loop below + // (each iteration writes `*rr = ...`). After all writes complete every + // slot is initialized, so it's safe to transmute the buffer to + // `Vec` via `assume_init`. + let mut res_elems: Vec> = Vec::with_capacity(m * n); + res_elems.resize_with(m * n, MaybeUninit::uninit); let mut i = 0; let mut j = 0; for rr in &mut res_elems { unsafe { - *rr = (0..k).fold(A::zero(), move |s, x| s + *lhs.uget((i, x)) * *rhs.uget((x, j))); + rr.write((0..k).fold(A::zero(), move |s, x| s + *lhs.uget((i, x)) * *rhs.uget((x, j)))); } j += 1; if j == n { @@ -304,6 +309,11 @@ where i += 1; } } + // SAFETY: every slot was initialized in the loop above. + let res_elems: Vec = unsafe { + let mut me = std::mem::ManuallyDrop::new(res_elems); + Vec::from_raw_parts(me.as_mut_ptr() as *mut A, me.len(), me.capacity()) + }; unsafe { ArrayBase::from_shape_vec_unchecked((m, n), res_elems) } }