SHOGUN  v2.0.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Cache.h
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 3 of the License, or
5  * (at your option) any later version.
6  *
7  * Written (W) 1999-2009 Soeren Sonnenburg
8  * Copyright (C) 1999-2009 Fraunhofer Institute FIRST and Max-Planck-Society
9  */
10 
11 #ifndef _CACHE_H__
12 #define _CACHE_H__
13 
14 #include <shogun/lib/common.h>
15 #include <shogun/io/SGIO.h>
17 #include <shogun/base/SGObject.h>
18 
19 #include <stdlib.h>
20 
21 namespace shogun
22 {
31 template<class T> class CCache : public CSGObject
32 {
34  struct TEntry
35  {
37  int64_t usage_count;
39  bool locked;
41  T* obj;
42  };
43 
44  public:
47  {
48  SG_UNSTABLE("CCache::CCache()", "\n");
49 
50  cache_block=NULL;
51  lookup_table=NULL;
52  cache_table=NULL;
53  cache_is_full=false;
55  entry_size=0;
56  }
57 
68  CCache(int64_t cache_size, int64_t obj_size, int64_t num_entries)
69  : CSGObject()
70  {
71  if (cache_size==0 || obj_size==0 || num_entries==0)
72  {
73  SG_INFO("doing without cache.\n");
74  cache_block=NULL;
75  lookup_table=NULL;
76  cache_table=NULL;
77  cache_is_full=false;
79  entry_size=0;
80  return;
81  }
82 
83  entry_size=obj_size;
84  nr_cache_lines=CMath::min((int64_t) (cache_size*1024*1024/obj_size/sizeof(T)), num_entries+1);
85 
86  SG_INFO("creating %d cache lines (total size: %ld byte)\n", nr_cache_lines, nr_cache_lines*obj_size*sizeof(T));
88  lookup_table=SG_MALLOC(TEntry, num_entries);
89  cache_table=SG_MALLOC(TEntry*, nr_cache_lines);
90 
94 
95  int64_t i;
96  for (i=0; i<nr_cache_lines; i++)
97  cache_table[i]=NULL;
98 
99  for (i=0; i<num_entries; i++)
100  {
101  lookup_table[i].usage_count=-1;
102  lookup_table[i].locked=false;
103  lookup_table[i].obj=NULL;
104  }
105  cache_is_full=false;
106 
107  //reserve the very last cache line
108  //as scratch buffer
109  nr_cache_lines--;
110  }
111 
112  virtual ~CCache()
113  {
117  }
118 
124  inline bool is_cached(int64_t number)
125  {
126  return (lookup_table && lookup_table[number].obj);
127  }
128 
134  inline T* lock_entry(int64_t number)
135  {
136  if (lookup_table)
137  {
138  lookup_table[number].usage_count++;
139  lookup_table[number].locked=true;
140  return lookup_table[number].obj;
141  }
142  else
143  return NULL;
144  }
145 
150  inline void unlock_entry(int64_t number)
151  {
152  if (lookup_table)
153  lookup_table[number].locked=false;
154  }
155 
163  T* set_entry(int64_t number)
164  {
165  if (lookup_table)
166  {
167  // first look for the element with smallest usage count
168  //int64_t min_idx=((nr_cache_lines-1)*random())/(RAND_MAX+1); //avoid the last elem and the scratch line
169  int64_t min_idx=0;
170  int64_t min=-1;
171  bool found_free_line=false;
172 
173  int64_t start=0;
174  for (start=0; start<nr_cache_lines; start++)
175  {
176  if (!cache_table[start])
177  {
178  min_idx=start;
179  min=-1;
180  found_free_line=true;
181  break;
182  }
183  else
184  {
185  if (!cache_table[start]->locked)
186  {
187  min=cache_table[start]->usage_count;
188  min_idx=start;
189  found_free_line=true;
190  break;
191  }
192  }
193  }
194 
195  for (int64_t i=start; i<nr_cache_lines; i++)
196  {
197  if (!cache_table[i])
198  {
199  min_idx=i;
200  min=-1;
201  found_free_line=true;
202  break;
203  }
204  else
205  {
206  int64_t v=cache_table[i]->usage_count;
207 
208  if (v<min && !cache_table[i]->locked)
209  {
210  min=v;
211  min_idx=i;
212  found_free_line=true;
213  }
214  }
215  }
216 
217  if (cache_table[nr_cache_lines-1]) //since this is an indicator for a full cache
218  cache_is_full=true;
219 
220  if (found_free_line)
221  {
222  // and overwrite it.
223  if ( (lookup_table[number].usage_count-min) < 5 && cache_is_full && ! (cache_table[nr_cache_lines] && cache_table[nr_cache_lines]->locked))
224  min_idx=nr_cache_lines; //scratch entry
225 
226  if (cache_table[min_idx])
227  cache_table[min_idx]->obj=NULL;
228 
229  cache_table[min_idx]=&lookup_table[number];
230  lookup_table[number].obj=&cache_block[entry_size*min_idx];
231 
232  //lock cache entry;
233  lookup_table[number].usage_count=0;
234  lookup_table[number].locked=true;
235  return lookup_table[number].obj;
236  }
237  else
238  return NULL;
239  }
240  else
241  return NULL;
242  }
243 
245  inline virtual const char* get_name() const { return "Cache"; }
246 
247  protected:
251  int64_t entry_size;
253  int64_t nr_cache_lines;
255  TEntry* lookup_table;
257  TEntry** cache_table;
260 };
261 }
262 #endif

SHOGUN Machine Learning Toolbox - Documentation