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感谢您的评论,这就是为什么我想知道是否有更好的解决方案。