优化内存搜索

时间:2014-09-25 22:27:14

标签: arrays performance loops optimization linked-list

我有4096个项目的多个实例。我需要在reocurring的基础上搜索和找到一个项目,我想优化它。由于不是所有的4096项都可以使用,我想,一种加快速度的方法是使用链表而不是数组。每当我必须搜索一个项目时,一旦找到它,我就把它放在列表的头部,以便下次它出现时,我只需要做很少的搜索(循环)工作。听起来不错吗?

EDIT1 我不认为二进制搜索树的想法实际上是我可以使用的,因为我已经对数据进行了排序,就像一个数组,即跟在前一个节点之后的每个节点都更大,这就失去了目的,不是吗?

我试图通过缓存来解决我的问题,并想出了类似的东西:

pending edit

但是我得到的输出表明它不像我想要的那样起作用:

关于如何改进这一点的任何建议?

4 个答案:

答案 0 :(得分:2)

在性能方面,只有一个重要的规则:衡量它!

在您的情况下,您可以举例说明两个不同的考虑因素,即理论运行时分析以及机器上的实际情况。两者都严重依赖于您的4096项目的特征。如果您的数据已经排序,您可以进行O(log n)搜索,如果它是未排序的,则最糟糕的情况是O(n)等。

关于链接列表的想法,您可能会有更多的硬件缓存未命中,因为数据不再存储在一起(空间局部性),即使您的理论考虑是正确的,也会导致执行速度变慢。

如果您对此类问题的一般兴趣,我推荐GoingNative 2013的这篇很酷的演讲 http://channel9.msdn.com/Events/GoingNative/2013/Writing-Quick-Code-in-Cpp-Quickly

答案 1 :(得分:1)

最糟糕的情况是,除非您按照Brett的建议对阵列或列表进行排序,否则您的搜索仍为O(N)。因此,使用排序列表,您会增加插入的复杂性(插入有序),但您的搜索速度会快得多。你的建议几乎就像一个"缓存。"我们很难说在没有任何关于在短期内再次搜索找到的项目的频率的情况下会有多大用处。显然,缓存有好处,这就是为什么我们在内存中拥有整个L1,L2,L3架构的原因。但是,它是否会为你效果还不确定。

答案 2 :(得分:1)

回应Edit1: 我想如果你的数据元素不大,比如只有几个字节甚至几十个字节,那么它们中就有4096个可以装入内存。在这种情况下,您需要的是哈希表。在C ++中,您使用unordered_map。例如,如果您的密钥类型为unorderedmap<int, ptr_to_your_node_type>,则可以定义O(1)并在int中获取该元素。

如果您可以很好地设计散列,最快的搜索可能是O(1),最糟糕的情况可能是O(n)。如果这些项很大且无法装入内存,则可以使用所谓的最近最少使用的缓存algorithm来节省内存。

LRU缓存的示例代码

template <typename K>
class Key_Age{
list<K> key_list;
unordered_map<K, typename list<K> :: iterator> key_pos;
public:
void access(K key){
    key_list.erase(key_pos[key]);
    insert_new(key);
}

void insert_new(K key){
    key_list.push_back(key);
    key_pos[key] = --key_list.end();
}

K pop_oldest(){
    K t = key_list.front();
    key_list.pop_front();
    return t;
}
};

class LRU_Cache{
int capacity;
Key_Age<int> key_age;
unordered_map<int, int> lru_cache;

public:
LRU_Cache(int capacity): capacity(capacity) {
}

int get(int key) {
    if (lru_cache.find(key) != lru_cache.end()) {
        key_age.access(key);
        return lru_cache[key];
    }
    return -1;
}

void set(int key, int value) {
    if (lru_cache.count(key) < 1) {
        if (lru_cache.size() == capacity) {
            int oldest_key = key_age.pop_oldest();
            lru_cache.erase(oldest_key);
        }
        key_age.insert_new(key);
        lru_cache[key] = value;
        return;
    }

    key_age.access(key);
    lru_cache[key] = value;
}

};

答案 3 :(得分:1)

如果您的数据可以放在二元搜索树中:http://en.wikipedia.org/wiki/Binary_search_tree

然后你可以使用一个名为Splay树的数据结构:“一个splay树是一个自我调整的二叉搜索树,它具有最近访问过的元素可以再次快速访问的附加属性”http://en.wikipedia.org/wiki/Splay_tree