Commit 82f50725 authored by Pavel Vainerman's avatar Pavel Vainerman

(Calibration): добавил кэш для оптимизации обращений.

parent dfe913db
......@@ -108,6 +108,8 @@
<br>\b filterT - Постоянная времени фильтра.
<br>\b caldiagram - Имя калибровочной диаграммы из секции <Calibrations>.
<br>\b cal_cachesize - Размер кэша в калибровочной диаграмме (Calibration.h)
<br>\b cal_cacheresort - Количество циклов обращения к кэшу, для вызова принудительной песортировки. (Calibration.h)
<br>\b threshold_aid - идентификатор аналогового датчика по которому формируется порог.
Используется для DI.
......
......@@ -46,6 +46,15 @@ y - калиброванное значение
Диаграмма позволяет задать множество точек. На отрезках между точками используется линейная аппроксимация.
Т.е. часто большую часть времени (во многих задачах) аналоговое значение, меняется в небольших пределах,
то добавлен кэш ( rawValue --> calValue ) по умолчанию на 5 значений. Размер кэша можно задать
(поменять или отключить) при помощи Calibration::setCacheSize().
\note Слишком большим задавать кэш не рекомендуется, т.к. тогда поиск по кэшу будет сопоставим с поиском по диаграмме.
Помимо этого, с учётом того, что каждое попадание в кэш обновляет счётчик обращений к значению, необходимо
пересортировывать весь кэш (чтобы наиболее часто используемые были в начале). Чтобы не делать эту операцию каждый
раз, сделан счётчик циклов. Т.е. через какое количество обращений к кэшу, производить принудительную пересортировку.
Значение по умолчанию - 5(размер кэша). Задать можно при помощи Calibration::setCacheResortCycle()
*/
class Calibration
{
......@@ -59,7 +68,7 @@ class Calibration
typedef float TypeOfValue;
/*! выход за границы диапазона */
static const TypeOfValue outOfRange;
static const long outOfRange;
/*!
Получение калиброванного значения
......@@ -98,7 +107,6 @@ class Calibration
/*! Возвращает крайнее правое значение 'y' встретившееся в диаграмме (ПОСЛЕ СОРТИРОВКИ ПО ВОЗРАСТАНИЮ 'x'!) */
inline long getRightRaw(){ return rightRaw; }
/*! построение характеристрики из конф. файла
\param name - название характеристики в файле
\param confile - файл содержащий данные
......@@ -114,9 +122,17 @@ class Calibration
return lround(val);
}
void setCacheSize( unsigned int sz );
inline unsigned int getCacheSize(){ return cache.size(); }
void setCacheResortCycle( unsigned int n );
inline unsigned int getCacheResotrCycle(){ return numCacheResort; }
// ---------------------------------------------------------------
friend std::ostream& operator<<(std::ostream& os, Calibration& c );
friend std::ostream& operator<<(std::ostream& os, Calibration* c );
// ---------------------------------------------------------------
/*! точка характеристики */
struct Point
{
......@@ -184,9 +200,42 @@ class Calibration
long minRaw, maxRaw, minVal, maxVal, rightVal, leftVal, rightRaw, leftRaw;
void insertToCache( const long raw, const long val );
private:
PartsVec pvec;
std::string myname;
// Cache
unsigned int szCache;
struct CacheInfo
{
CacheInfo():val(0),raw(outOfRange),cnt(0){}
CacheInfo( const long r, const long v ):val(v),raw(r),cnt(0){}
long val;
long raw;
unsigned long cnt; // счётчик обращений
// сортируем в порядке убывания(!) обращений
// т.е. наиболее часто используемые (впереди)
inline bool operator<( const CacheInfo& r ) const
{
if( r.raw == outOfRange )
return true;
// неинициализированные записи, сдвигаем в конец.
if( raw == outOfRange )
return false;
return cnt > r.cnt;
}
};
typedef std::vector<CacheInfo> ValueCache;
ValueCache cache;
unsigned long numCacheResort; // количество обращений, при которых происходит перестроение (сортировка) кэша..
unsigned long numCallToCache; // текущий счётчик обращений к кэшу
};
// -----------------------------------------------------------------------------
#endif // Calibration_H_
......
......@@ -9,7 +9,7 @@
using namespace std;
using namespace UniSetTypes;
// ----------------------------------------------------------------------------
const Calibration::TypeOfValue Calibration::outOfRange = std::numeric_limits<Calibration::TypeOfValue>::max();
const long Calibration::outOfRange = std::numeric_limits<Calibration::TypeOfValue>::max();
// ----------------------------------------------------------------------------
Calibration::Part::Part():
k(0)
......@@ -105,7 +105,11 @@ Calibration::TypeOfValue Calibration::Part::calcX( const TypeOfValue& y ) const
Calibration::Calibration():
minRaw(0),maxRaw(0),minVal(0),maxVal(0),rightVal(0),leftVal(0),rightRaw(0),leftRaw(0),
pvec(50),
myname("")
myname(""),
szCache(5),
cache(5),
numCacheResort(5),
numCallToCache(5)
{
}
......@@ -114,14 +118,22 @@ myname("")
Calibration::Calibration( const string& name, const string& confile ):
minRaw(0),maxRaw(0),minVal(0),maxVal(0),rightVal(0),leftVal(0),rightRaw(0),leftRaw(0),
pvec(50),
myname(name)
myname(name),
szCache(5),
cache(5),
numCacheResort(5),
numCallToCache(5)
{
build(name,confile,0);
}
// ----------------------------------------------------------------------------
Calibration::Calibration( xmlNode* node ):
minRaw(0),maxRaw(0),minVal(0),maxVal(0),rightVal(0),leftVal(0),rightRaw(0),leftRaw(0),pvec(100)
minRaw(0),maxRaw(0),minVal(0),maxVal(0),rightVal(0),leftVal(0),rightRaw(0),leftRaw(0),pvec(100),
szCache(5),
cache(5),
numCacheResort(5),
numCallToCache(5)
{
UniXML_iterator it(node);
myname = it.getProp("name");
......@@ -214,7 +226,7 @@ void Calibration::build( const string& name, const string& confile, xmlNode* roo
{
leftRaw = beg->left_x();
leftVal = beg->left_y();
end--;
--end;
rightRaw = end->right_x();
rightVal = end->right_y();
}
......@@ -257,18 +269,69 @@ long Calibration::getValue( long raw, bool crop_raw )
if( raw > rightRaw )
return (crop_raw ? rightVal : outOfRange);
if( szCache ) // > 0
{
for( ValueCache::iterator c=cache.begin(); c!=cache.end(); ++c )
{
if( c->raw == raw )
{
--numCallToCache;
c->cnt++;
if( numCallToCache )
return c->val;
long val = c->val; // после сортировки итератор станет недействительным, поэтому запоминаем..
sort(cache.begin(),cache.end());
numCallToCache = numCacheResort;
return val;
}
}
}
PartsVec::iterator fit = find_range(raw, pvec.begin(), pvec.end());
if( fit == pvec.end() )
{
if( szCache )
insertToCache(raw,outOfRange);
return outOfRange;
}
TypeOfValue q = fit->getY(raw);
if( q != outOfRange )
{
if( szCache )
insertToCache(raw, tRound(q) );
return tRound(q);
}
if( szCache )
insertToCache(raw,outOfRange);
return outOfRange;
}
// ----------------------------------------------------------------------------
void Calibration::setCacheResortCycle( unsigned int n )
{
numCacheResort = n;
numCallToCache = n;
}
// ----------------------------------------------------------------------------
void Calibration::setCacheSize( unsigned int sz )
{
sort(cache.begin(),cache.end()); // в порядке уменьшения обращений (см. CacheInfo::operator< )
cache.resize(sz);
szCache = sz;
}
// ----------------------------------------------------------------------------
void Calibration::insertToCache( const long raw, const long val )
{
sort(cache.begin(),cache.end()); // пересортируем в порядке уменьшения обращений (см. CacheInfo::operator< )
cache.pop_back(); // удаляем последний элемент (как самый неиспользуемый)
cache.push_back( CacheInfo(raw,val) ); // добавляем в конец..
sort(cache.begin(),cache.end()); // пересортируем с учётом вставки
}
// ----------------------------------------------------------------------------
long Calibration::getRawValue( long cal, bool range )
{
for( PartsVec::iterator it=pvec.begin(); it!=pvec.end(); ++it )
......
......@@ -522,7 +522,13 @@ bool IOBase::initItem( IOBase* b, UniXML_iterator& it, SMInterface* shm,
std::string caldiagram( it.getProp("caldiagram") );
if( !caldiagram.empty() )
{
b->cdiagram = UniSetExtensions::buildCalibrationDiagram(caldiagram);
if( !it.getProp("cal_cachesize").empty() )
b->cdiagram->setCacheSize(it.getIntProp("cal_cachesize"));
if( !it.getProp("cal_cacheresort").empty() )
b->cdiagram->setCacheResortCycle(it.getIntProp("cal_cacheresort"));
}
}
else if( b->stype == UniversalIO::DI || b->stype == UniversalIO::DO )
{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment