缓存它是否缓存它(生成它),这就是问题所在

时间:2015-01-14 04:03:37

标签: c++

我有100个double值的集合,必须多次用修复int变量除以:

unsigned int current_interval = double_value / int_value;

我需要知道以下简单缓存是否会更便宜(以及为什么?):

std::map<double_value,current_interval> cache;
//...
unsigned int get_interval(double_value / int_value){
    if((it = cache.find(double_value)) != cache.end()
    {
     return it->second;
    }
    unsigned int current_interval = double_value / int_value;
    cache[double_value] = current_interval;
    return current_interval;
}

谢谢

1 个答案:

答案 0 :(得分:2)

摘要:执行重复分割可能比在地图中查找值更快

<强>详细信息:

我认为这是一个有趣的问题。至少从与浮点除法相比的地图查找的执行时间的角度来看。在解决这个问题之前,我想重申其中两条评论:

1)如果你真的只有100个双打,你除以一个固定的值,然后使用很多次,我希望你应该能够转换你的算法直接使用这个结果。我希望这比提出的缓存算法更有效。

2)不要在地图中使用double作为关键字。

现在谈谈主要问题。为了回答这个问题,我写了两个小程序。第一个只是在大小为100的地图中查找值。第二个执行浮点除法。我已经包含了完整的源代码,以防有人想要复制我的结果。另外对于第二个程序,我只是为了保持相同的结构而包含一些额外的代码,但是在第二个循环中重要的是。


<强> map.cpp

#include <map>
#include <stdlib.h>

std::map<int,int> testmap;

int main(int argc, char **argv) {
  int count = atoi(argv[1]);
  int val   = atoi(argv[2]);
  int total = 0;

  for(int i = 0; i < 100; i++) {
    testmap[i] = val + i;
  }

  for(int i = 0; i < count; i++) {
    for(int j = 0; j < 100; j++) {
      total += testmap[j];
    }
  }

  return total;
}

<强> double.cpp

#include <map>
#include <stdlib.h>

std::map<int,int> testmap;

int main(int argc, char **argv) {
  int count = atoi(argv[1]);
  double val   = atof(argv[2]);
  double total = 0;

  for(int i = 0; i < 100; i++) {
    testmap[i] = val + i;
  }

  for(int i = 0; i < count; i++) {
    for(int j = 0; j < 100; j++) {
      total += val / j;
    }
  }

  return total;
}

我用O1和O3编译,以确保编译器没有优化循环。我还测试了一些不同的迭代大小,以确保执行时间与迭代计数一致。

我在使用Intel(R) Xeon(R) CPU E3-1275 v3 @ 3.50GHz

编译的g++ (GCC) 4.9.2系统上运行了测试

对于O1,运行10000000次迭代的结果是:

map: 7.1 seconds 
double: 3.6 seconds

对于O3,我的结果是:

map: 5.3 seconds
double: 3.5 seconds

所以区别并不大,但很明显,我在这里写的小微基准测试中,划分实现速度更快。而且实施起来也更简单。因此,我认为尝试记住除法结果,然后在地图中查找它们的可能性要小于在需要时简单计算值的速度。为了使memoization有用,基本操作需要比现代CPU中大量优化的浮点除法更昂贵。