3 ms·
That just means the compiler needs more work around generating optimal code. Rust has some similar idioms and does much better, with the difference between "C-l
by api 5y ago
That just means the compiler needs more work around generating optimal code. Rust has some similar idioms and does much better, with the difference between "C-like" Rust and idiomatic Rust usually being small to nonexistent. With Rust you can still sometimes hit edge cases though where the compiler spits out slow code for some idiom that should be zero cost.
- saagarjha 5y agoYes, Swift lags behind on this. Part of it is a language design thing (lots of extra allocations by default, certain invariants cannot be reasonably be expressed to the compiler, lots of optimization information is thrown away before it hits the middle end), part of it (IMO) is a priority thing. Rust has an extremely strong desire to compare favorably against C/C++, and missed optimizations make it look bad. Swift is working in this area but it seems to be late to the game. Also, just to be entirely clear, an example like this (once I “fixed” it) is probably the best Swift can reasonably expect to get, since it hits all the hardcoded semantic hints that Array has been annotated with. It actually does get quite close to the unidiomatic version; save for some extra bounds checks from the zip and a dubious double move, it’s basically done as well as it could with constant propagation and inlining. More complex examples are unlikely to fare as well.
- nerdponx 5y agoI was under the impression that this category of optimizations ("deforestation") is difficult, and requires some immutability/side-effect-free guarantees to be performed effectively. Is that kind of optimization even feasible in Swift?
- zozbot234 5y agoBound checks can be an issue in Rust as well, actually. It's often worthwhile to hoist them manually out of loops, which usually enables the compiler to optimize them out within the loop and even vectorize the resulting code. (This can't happen automatically because the default semantics generally involve a panic or exception to be triggered when the check fails; there's no way to optimize this further.)
- api 5y agoA trick I've found to eliminate them in a few cases: pass &[T; size] instead of &[T] when dealing with statically sized arrays. The compiler will elide bounds checking a lot more aggressively with statically sized arrays since the bounds are known at compile time.
- saagarjha 5y agoIn this case none of the accesses should fail because they can all be statically observed to be in-bounds; unfortunately the Swift compiler was not able to see that.
- mhh__ 5y agoEmphasis on similar, though. This sometimes comes up when people are discussing D ranges, and it's important to keep in mind that in some case the autovectorization cannot happen because a tradeoff was made that we value locality over parallelizism i.e. just reduce rather than map-reduce. Transforming from reduce to map-reduce is usually very trivial, but has to be kept in mind