我有一个接受两个输入的函数f(a,b)。我不知道提前使用a和b的哪个值。我对记忆有点浪费我很好(我关心速度)。我希望能够检查f(a,b)的输出是否已经传递,如果是,则再次传递该输出而不重新运行f(a,b)过程。
使用装饰器在Python中很容易做到,但是C ++在我的脑海中已经过时了。答案 0 :(得分:6)
答案 1 :(得分:3)
海报问道:
我希望能够检查f(a,b)的输出是否已经传递,如果是,则再次传递该输出而不重新运行f(a,b)过程。
使用std::map
在C ++中非常容易。该函数具有两个参数的事实意味着我们可以使用std::pair
来描述它们。
#include <map>
#include <iostream>
uint64_t real_f(int a, int b) {
std::cout << "*";
// Do something tough:
return (uint64_t)a*b;
}
uint64_t memo_f(int a, int b) {
typedef std::pair<int, int> key;
typedef std::map<key, uint64_t> map;
static map m;
key k(a,b);
map::iterator it = m.find(k);
if(it == m.end()) {
return m[k] = real_f(a, b);
}
return it->second;
}
int main () {
std::cout << memo_f(1, 2) << "\n";
std::cout << memo_f(3, 4) << "\n";
std::cout << memo_f(1, 2) << "\n";
std::cout << memo_f(3, 4) << "\n";
std::cout << memo_f(5, 6) << "\n";
}
上述程序的输出是:
*2
*12
2
12
*30
没有星号的行代表缓存结果。
答案 2 :(得分:1)
使用C ++ 11,您可以使用任务和期货。让f
成为您的职能:
int f(int a, int b)
{
// Do hard work.
}
然后你会安排函数执行,它会返回一个返回值的句柄。此句柄称为 future :
template <typename F>
std::future<typename std::result_of<F()>::type>
schedule(F f)
{
typedef typename std::result_of<F()>::type result_type;
std::packaged_task<result_type> task(f);
auto future = task.get_future();
tasks_.push_back(std::move(task)); // Queue the task, execute later.
return std::move(future);
}
然后,您可以按如下方式使用此机制:
auto future = schedule(std::bind(&f, 42, 43)); // Via std::bind.
auto future = schedule([&] { f(42, 43); }); // Lambda alternative.
if (future.has_value())
{
auto x = future.get(); // Blocks if the result of f(a,b) is not yet availble.
g(x);
}
免责声明:我的编译器不支持任务/期货,因此代码可能有一些粗略的边缘。
答案 3 :(得分:0)
关于这个问题的要点是计算f(a,b)和保持某种查找表以缓存结果之间CPU和RAM的相对费用。
由于128位索引长度的穷举表尚不可行,我们需要将查找空间缩小到可管理的大小 - 如果没有在您的应用程序内部考虑,则无法完成此操作:
我只是从一个固定大小的(a,b, f(a,b))
元组数组开始,然后进行线性搜索。根据您上面提到的模式,您可能希望
(a,b,f(a,b),count)
元组和元组,其中最小的计数被驱逐 - 这对于非本地化的事件很有用如果后者变得越来越复杂,您可能还希望将重复计算与查找机制进行对比:std::map
和freinds不是免费的,即使它们是高质量的实现。
答案 4 :(得分:0)
唯一简单的方法是使用 std::map
。 std::unordered_map
不起作用。我们不能使用 std::pair
作为无序映射中的键。您可以执行以下操作,
std::map<pair<int, int>, int> mp;
int func(int a, int b)
{
if (mp.find({a, b}) != mp.end()) return mp[{a, b}];
// compute f(a, b)...
mp[{a, b}] = // computed value;
return mp[{a, b}];
}