optimisation pour la mémorisation d'une fonction avec un type de retour lourd [review de code]
Bonjour à toutes et à tous ! :D
Je cherche à mémoizer une fonction F. J'ai piqué des bouts de code ici : http://cpptruths.blogspot.com/2012/0...moization.html
Toutefois, la différence est que dans mon cas, la fonction F renvoie un foncteur D très lourd (c'est une distribution avec un gros support, qui est longue à construire, et coûteuse à copier). Mon but est donc à la fois de construire D une seule fois, mais aussi d'éviter toutes les opérations de copies pour amener D là où on en a besoin.
J'ai donc modifié le code initial pour aboutir à la version suivante. Comme c'est un bout de code critique, j'aimerais m'assurer que je ne fais pas d'opérations inutiles. Sauf que je suis sûr que j'en ai fait tout plein ! :mouarf: Qu'en pensez-vous ?
Code:
1 2 3 4 5 6 7 8 9 10
| template<typename Ret, typename... Args>
auto memoize( Ret(*func)(Args...) ) {
auto cache = std::make_shared<std::map<std::tuple<Args...>, Ret>>();
return ([=](Args... args) mutable {
std::tuple<Args...> t(args...);
if (cache->find(t) == cache->end())
(*cache)[t] = std::move(func(args...));
return std::cref((*cache)[t]);
});
} |
Code:
1 2 3 4 5 6 7 8 9 10 11
|
template <typename Sig, Sig funcptr>
struct static_memoizer;
template <typename F_ret, typename... F_args, F_ret (*func)(F_args...)>
struct static_memoizer<F_ret (*)(F_args...), func> {
static auto get() {
static auto mfunc (memoize(func));
return mfunc;
}
}; |
Et du coup je l'utilise comme ça :
Code:
1 2 3 4 5 6 7 8 9 10
| template<typename BigInt, typename BigFloat>
struct in_memoized_distribution{
template<typename Generator>
static std::vector<unsigned int> const& build(unsigned int k, unsigned int N, Generator& g){
return utils::static_memoizer<
decltype(&coalescence::make_occupancy_spectrum_distribution<BigInt, BigFloat>),
&coalescence::make_occupancy_spectrum_distribution<BigInt, BigFloat>
>::get()(k,N)(g);
}
}; |
Merci d'avance ;)