检索16k键值对的最快方法是什么?

时间:2012-12-16 04:44:44

标签: c++ c arrays map hashtable

好的,这是我的情况:

  • 我有一个函数 - 让我们说U64 calc (U64 x) - 它接受一个64位整数参数,执行一些CPU密集型操作,并返回一个64位值
  • 现在,鉴于我事先知道了该函数的所有可能输入(x s)(虽然有大约16000),我认为预先计算它们然后按需获取它们会更好(来自类似阵列的结构)。
  • 理想情况是将它们全部存储在某个数组U64 CALC[]中并按索引检索它们(再次x
  • 这就是问题:我可能知道我的计算函数的可能输入是什么,但它们绝对是不连续(例如,不是从1到16000,但值可能会低至为0和高达几万亿 - 总是具有64位范围)

E.G。

  X        CALC[X]
-----------------------
  123123   123123123
  12312    12312312
  897523   986123

  etc.

以下是我的问题:

  • 你会如何储存它们?
  • 您更喜欢哪种解决方法?
  • 现在,鉴于这些值(来自CALC必须以每秒数千到数百万次的速度访问,这将是性能方面的最佳解决方案?

注意:我没有提到任何我曾经想过或尝试过的事情,以免将答案变成A和B类型的争论,而且主要是不影响任何人...

5 个答案:

答案 0 :(得分:1)

执行memonization,或简单地说,缓存已经计算过的值并计算新值。您应该对输入进行散列并检查该结果的缓存。您甚至可以从一组缓存值开始,您认为该函数将被更频繁地调用。除此之外,我认为你不需要像其他答案所说的那样去任何极端。做事简单,当您完成应用程序后,您可以使用分析工具查找瓶颈。

编辑:一些代码

#include <iostream>
#include <ctime>
using namespace std;

const int MAX_SIZE = 16000;

int preCalcData[MAX_SIZE] = {};

int getPrecalculatedResult(int x){
 return preCalcData[x];
}

void setupPreCalcDataCache(){
  for(int i = 0; i < MAX_SIZE; ++i){
    preCalcData[i] = i*i; //or whatever calculation
  }
}

int main(){
  setupPreCalcDataCache();

  cout << getPrecalculatedResult(0) << endl;
  cout << getPrecalculatedResult(15999) << endl;

  return 0;
}    

答案 1 :(得分:1)

制作一组关键值对的结构。

按键对数组进行排序,将其作为静态数组放入程序中,只能是128kbyte。

然后在你的程序中,按键查找一个简单的二进制文件,平均只需要14次密钥比较才能找到正确的值。在现代电脑上应该能够达到每秒3亿次仰视的速度。

您可以使用qsort进行排序,并使用bsearch搜索std lib函数。

答案 2 :(得分:0)

我不会太担心表现。这个简单的例子,使用数组和二进制搜索lower_bound

#include <stdint.h>
#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <memory>

const int N = 16000;
typedef std::pair<uint64_t, uint64_t> CALC;
CALC calc[N];

static inline bool cmp_calcs(const CALC &c1, const CALC &c2)
{
    return c1.first < c2.first;
}

int main(int argc, char **argv)
{
    std::iostream::sync_with_stdio(false);
    for (int i = 0; i < N; ++i)
        calc[i] = std::make_pair(i, i);

    std::sort(&calc[0], &calc[N], cmp_calcs);

    for (long i = 0; i < 10000000; ++i) {
        int r = rand() % 16000;
        CALC *p = std::lower_bound(&calc[0], &calc[N], std::make_pair(r, 0), cmp_calcs);
        if (p->first == r)
            std::cout << "found\n";
    }

    return 0;
}

并使用

编译
g++ -O2 example.cpp

包括设置,在我5岁的PC上大约2秒内进行了10,000,000次搜索。

答案 3 :(得分:0)

您需要有效地存储16,000个值,最好是在内存中。我们假设这些值的计算比从存储中访问它们更耗时。

您可以使用许多不同的数据结构来完成工作,包括数据库。如果您以可查询的块访问这些值,那么数据库开销很可能会被吸收并在您的处理过程中传播。

你在问题​​标签中已经提到了map和hashmap(或hashtable),但这些可能不是你问题的最佳答案,尽管它们可以做得很好,只要散列函数不比直接计算目标UINT64值,该值必须是您的参考基准。

可能更适合。有了一些经验,我可能会选择B树:它们支持相当好的序列化。这应该让您提前在不同的程序中准备数据集。 VEB树有一个非常好的访问时间(O(log log(n)),但我不知道它们是多么容易被序列化。

稍后,如果您需要更高的性能,了解“数据库”的使用模式以了解您可以在商店顶部实施的caching techniques也很有趣。

答案 4 :(得分:-2)

使用std :: pair比任何map更好。

但如果我是你,我首先使用std :: list来存储数据,在我得到它们之后,我将它们移动到一个简单的向量中,如果你实现一个简单的二叉树搜索,那么检索速度会非常快自己。