Le 27/06/15 16:48, Louis Dionne a écrit :
Joel de Guzman
writes: [...] Your tests focused on a mere subset of Fusion which is the least optimized: fusion::vector. Your tests do not cover other areas such as views, and other containers. Frankly, I thought fusion::vector would be the most efficient container. Isn't vector documented as such? Quoting from the documentation:
vector is the simplest of the Fusion sequence container (a vector with N elements is just a struct with N members), and in many cases the most efficient.
I can imagine a case, when say you push_back or insert where views should shine. It's the difference between copy by value and pass by reference. Try doing that with large tuple elements (those without resources and are not efficiently moved). Actually, have you tried reverse with large tuples like bitmaps and stuff?
Hmmmm, how did you test reverse in Fusion BTW? Fusion reverse should return a view with ZERO(!) copy. Did you create another vector from the reverse_view? I guess so, since your test subject is Fusion vector. In that case, you are not doing it right! You don't copy to another vector. You should use the results as-is. Lazily.
For that matter, the same is true with transform! Fusion returns transform_view. You should get zero overhead with those because they are lazy. If you are copying back to a fusion vector, then you are not doing it right. Have you tried accessing, say only the Nth element instead of (presumably) copying back to a vector before accessing the Nth element? or how about transforming only a range within the container?
It seems you are doing your tests unfairly using eager evaluation (Hana) instead of lazy evaluation (Fusion). There seems to be a larger issue here. That issue is: How to benchmark lazy computations and eager computations? To illustrate the problem, consider the following "benchmark":
transforming a vector in C++:
#include <algorithm> #include <vector>
int main() { std::vector<int> xs(1000); std::vector<int> ys; ys.reserve(xs.size()); std::transform(xs.begin(), xs.end(), std::back_inserter(ys), [](int x) { return x + 1; }); }
transforming a list in Haskell:
import Data.List
main = do let xs = take 1000 (repeat 0) let ys = fmap (+1) xs return ()
Written this way, the Haskell code will always be faster because it does not do anything, since it is lazy. However, that does not tell us much about what we're interested in. What we'd like to know is how the above code behaves when I _actually_ access the elements of the lazy list. So, of course I copy the result into vectors when benchmarking Fusion algorithms, since otherwise there's nothing to benchmark!
I think this ought to be explained in the documentation, but I don't think it invalidates Hana's claims. For equivalent functionality (i.e. when accessing all the members of the resulting container, which is assumed to usually be the case), Hana will perform as good as Fusion.
Instead of using a fusion::vector as a return of transform or reverse, you could just iterate on the result to e.g. calculate something simple. Vicente