Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.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++_Algorithm_C++11_Caching - Fatal编程技术网

C++ 度量空间的高性能相似性缓存

C++ 度量空间的高性能相似性缓存,c++,algorithm,c++11,caching,C++,Algorithm,C++11,Caching,问题: 首先:这是一个高性能的应用程序,所以时间执行是最重要的方面。我有一个后端系统,可以计算一些昂贵的功能: template<typename C, typename R> R backEndFunction (C &code){ ... } 我的问题: /** * C = code type * R = result type * D = distance type (e.g. float for euclidean) */ template <

问题

首先:这是一个高性能的应用程序,所以时间执行是最重要的方面。我有一个后端系统,可以计算一些昂贵的功能:

template<typename C, typename R>
R backEndFunction (C &code){
  ...
}
我的问题:

/**
 *  C = code type
 *  R = result type
 *  D = distance type (e.g. float for euclidean)
 */
template <typename C, typename R, typename D>
class Cache {

typedef std::shared_ptr<cc::Distance<C,D>> DistancePtr;

public:
    Cache(const DistancePtr distance, const std::function<R(C)> &backEnd, const size_t size = 10000, const float treshold = 0);
    R Query(const C &query);
    void PrintCache();
private:
    struct Compare{
        Compare(D val = std::numeric_limits<D>::max(), size_t index = 0) : val(val), index(index) {}
        D val;
        size_t index;
    };
    #pragma omp declare reduction(minimum : struct Compare : omp_out = omp_in.val < omp_out.val ? omp_in : omp_out) initializer (omp_priv=Compare())

    struct CacheElem{
        CacheElem(const C &code, const R &result, std::list<size_t>::iterator listElem) : code(code), result(result), listElem(listElem) {}
        C code;
        R result;
        std::list<size_t>::iterator listElem; //pointing to corresponding element in lru0
    };
    DistancePtr distance;
    std::function<R(C)> backEnd;
    std::vector<CacheElem> values;
    std::list<size_t> lru;
    float treshold;
    size_t size;
};


template <typename C, typename R, typename D>
Cache<C,R,D>::Cache(const DistancePtr distance, const std::function<R(C)> &backEnd, const size_t size, const float treshold)
: distance(distance), backEnd(backEnd), treshold(treshold), size(size) {
    values.reserve(size);
    std::cout<<"CACHE SETUP: size="<<size<<" treshold="<<treshold<<std::endl;
}

template <typename C, typename R, typename D>
void Cache<C,R,D>::PrintCache() {
    std::cout<<"LRU: ";
    for(std::list<size_t>::iterator it=lru.begin(); it != lru.end(); ++it)
        std::cout<<*it<<" ";
    std::cout<<std::endl;
    std::cout<<"VALUES: ";
    for(size_t i=0; i<values.size(); i++)
        std::cout<<"("<<values[i].code<<","<<values[i].result<<","<<*(values[i].listElem)<<")";
    std::cout<<std::endl;
}

template <typename C, typename R, typename D>
R Cache<C,R,D>::Query(const C &query){
    PrintCache();
    Compare min;
    R result;
    std::cout<<"query="<<query<<std::endl;
    //Find the cached element with min distance
    #pragma omp parallel for reduction(minimum:min)
    for(size_t i=0; i<values.size(); i++){
        D d = distance->compute(query, values[i].code);
        #pragma omp critical
        {
        std::cout<<omp_get_thread_num()<<" min="<<min.val<<" distance("<<query<<" "<<values[i].code<<")= "<<d;
        if(d < min.val){
            std::cout<<" NEW MIN!";
            min.val = d;
            min.index = i;
        }
        std::cout<<std::endl;
        }
    }
    std::cout<<"min.val="<<min.val<<std::endl;
    //Cache hit
    if(!lru.empty() && min.val < treshold){
        std::cout<<"cache hit with index="<<min.index<<" result="<<values[min.index].result<<" distance="<<min.val<<std::endl;
        CacheElem hitElem = values[min.index];
        //take the hit element to top of the queue
        if( hitElem.listElem  != lru.begin() )
            lru.splice( lru.begin(), lru, hitElem.listElem, std::next( hitElem.listElem ) );
        result = hitElem.result;
    }
    //cache miss
    else {
        result = backEnd(query);
        std::cout<<"cache miss backend="<<result;
        //Cache reached max capacity
        if(lru.size() == size){
            //last item (the one that must be removed) value is its corresponding index in values
            size_t lastIndex = lru.back();
            //remove last element
            lru.pop_back();
            //insert new element in the list
            lru.push_front(lastIndex);
            //insert new element in the value vector, replacing the old one
            values[lastIndex] = CacheElem(query, result, lru.begin());
            std::cout<<" index to replace="<<lastIndex;
        }
        else{
            lru.push_front(values.size()); //since we are going to inser a new element, we don't need to do size()-1
            values.push_back(CacheElem(query, result, lru.begin()));
        }
        std::cout<<std::endl;
    }
    PrintCache();
    std::cout<<"-------------------------------------"<<std::endl;
    return result;
}
  • 知道了每个查询我都必须检查所有缓存的元素,你认为有比我更高性能的解决方案吗?特别考虑使用
    std::向量值的解决方案
    std::列出lru
  • 如果这是最好的解决方案,我们知道对于高性能应用程序来说,
    std::list
    不是一个好的解决方案,但是对于给定的问题,我没有找到更好的解决方案。你知道有什么类似队列的结构吗?你可以把随机元素放在队列的顶部,然后我必须
    向后弹出
    向前推
    a(如本例所示)

  • 似乎更适合IMO…@ildjarn我考虑过这一点,但我问了两个具体的编程问题,其中我对效率有疑问。我认为Stackoverflow适合于此,不是吗?我不会说询问是否有方法使代码更快是非常具体的。。。来自:“如果您正在以下方面寻找项目中特定工作代码的反馈…•性能…那么您的位置是正确的!”
    list
    很少是一个好主意。@Yakk感谢您的评论,这就是为什么我想知道是否有更好的解决方案。似乎更适合IMO…@ildjarn我考虑过这个问题,但我问了两个具体的编程问题,其中我对效率有疑问。我认为Stackoverflow适合于此,不是吗?我不会说询问是否有方法使代码更快是非常具体的。。。来自:“如果您正在以下方面寻找项目中特定工作代码的反馈…•性能…那么您就在正确的位置!”
    列表
    很少是一个好主意。@Yakk感谢您的评论,这就是为什么我想知道是否有更好的解决方案。