Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/126.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在C+中使用两个输入来记忆函数+;_C++ - Fatal编程技术网

C++ 在C+中使用两个输入来记忆函数+;

C++ 在C+中使用两个输入来记忆函数+;,c++,C++,我有一个函数,f(a,b),它接受两个输入。我事先不知道将使用a和b的哪些值。我不介意在记忆上有点浪费(我在乎速度)。我希望能够检查f(a,b)的输出是否已经交付,如果已经交付,则在不重新运行f(a,b)过程的情况下再次交付该输出 在Python中使用装饰器是很容易的,但是C++在我的脑子里是这样的。 < P>我会使用(或者也许是 STD::unOrdEdjPad < /COD>),其键是A,或者可能使用地图。 在这种情况下,C++11的改进可能会有所帮助。或者一些增强功能。使用C++11,您可

我有一个函数,
f(a,b)
,它接受两个输入。我事先不知道将使用
a
b
的哪些值。我不介意在记忆上有点浪费(我在乎速度)。我希望能够检查
f(a,b)
的输出是否已经交付,如果已经交付,则在不重新运行
f(a,b)
过程的情况下再次交付该输出

在Python中使用装饰器是很容易的,但是C++在我的脑子里是这样的。

< P>我会使用(或者也许是<代码> STD::unOrdEdjPad < /COD>),其键是A,或者可能使用地图。
在这种情况下,C++11的改进可能会有所帮助。或者一些增强功能。

使用C++11,您可以使用任务和未来。让
f
成为您的功能:

int f(int a, int b)
{
    // Do hard work.
}
然后,您将计划函数执行,这将返回返回值的句柄。此句柄称为未来:

免责声明:我的编译器不支持任务/未来,因此代码可能有一些粗糙的边缘。

海报要求:

我希望能够检查f(a,b)的输出是否已经交付,如果已经交付,则在不重新运行f(a,b)进程的情况下再次交付该输出

在C++中使用一个<代码> STD::MAP< /COD>很容易。函数正好有两个参数,这意味着我们可以使用
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";
}

不带星号的行表示缓存的结果。

这个问题的要点是计算f(a,b)和保留某种查找表以缓存结果之间CPU和RAM的相对开销

由于128位索引长度的详尽表格(目前)不可行,我们需要将查找空间缩小到可管理的大小-如果没有应用程序内部的一些考虑,这是无法做到的:

  • 功能输入的实际使用空间有多大?这里面有规律吗
  • 时间成分呢?您是否希望重复的计算彼此接近或沿时间线分布
  • 分布情况如何?您是否假设索引空间的一小部分会占用大部分函数调用
我只需要从一个固定大小的
(a,b,f(a,b))
元组数组和一个线性搜索开始。根据上面提到的模式,您可能希望

  • 窗口滑动(在缓存未命中时删除最旧的):这对于本地化的重新发生很好
  • have
    (a,b,f(a,b),count)
    具有最小计数的元组的元组被排除-这对于非本地化的事件很好
  • 让一些键函数确定缓存中的位置(这有利于索引空间的使用)
  • 无论Knuth或Google想到了什么

如果查找机制变得越来越复杂,您可能还希望对重复计算进行基准测试:
std::map
和freinds不是免费的,即使它们是高质量的实现。

唯一简单的方法是使用
std::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}];
}
std::map-mp;
int func(int a,int b)
{
if(mp.find({a,b})!=mp.end())返回mp[{a,b}];
//计算f(a,b)。。。
mp[{a,b}]=//计算值;
返回mp[{a,b}];
}

输入的数据类型是什么?我写了一个无符号64位整数。到目前为止,这些答案似乎相当复杂。。。有没有一种方法可以让我声明一个二维向量,然后直接检索/设置它?@JohnSmith:你不能创建一个由单个64位整数索引的向量,更不用说两个了。您需要
2**128
元素!只是预初始化它会非常慢。我认为这没有帮助。您仍然需要一种方法来查找与特定的
(a,b)
元组对应的
未来的
对象,如果这样做,您可以只查找结果。@BenVoigt:如果
f
便宜,我同意。但据我所知,
f
的实际计算可能会很昂贵。小小的挑剔,
m[k]
将进行另一次搜索,而
m.find(k)
已经执行了。为了避免这一点,考虑使用<代码> m插入()< <代码> >或>代码> m(或)>代码>。为什么您认为我们不能使用<代码> STD::unOrdEdjPMAP?也许应该提供一个散列函数(我没有检查它),就是这样。是的,我们不能使用无序映射,除非你为它提供一个散列函数。
#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
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}];
}