Commit 689094b3 authored by Pavel Vainerman's avatar Pavel Vainerman

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

parent 3d559e0a
...@@ -108,6 +108,8 @@ ...@@ -108,6 +108,8 @@
<br>\b filterT - Постоянная времени фильтра. <br>\b filterT - Постоянная времени фильтра.
<br>\b caldiagram - Имя калибровочной диаграммы из секции <Calibrations>. <br>\b caldiagram - Имя калибровочной диаграммы из секции <Calibrations>.
<br>\b cal_cachesize - Размер кэша в калибровочной диаграмме (Calibration.h)
<br>\b cal_cacheresort - Количество циклов обращения к кэшу, для вызова принудительной песортировки. (Calibration.h)
<br>\b threshold_aid - идентификатор аналогового датчика по которому формируется порог. <br>\b threshold_aid - идентификатор аналогового датчика по которому формируется порог.
Используется для DI. Используется для DI.
......
...@@ -46,6 +46,15 @@ y - калиброванное значение ...@@ -46,6 +46,15 @@ y - калиброванное значение
Диаграмма позволяет задать множество точек. На отрезках между точками используется линейная аппроксимация. Диаграмма позволяет задать множество точек. На отрезках между точками используется линейная аппроксимация.
Т.е. часто большую часть времени (во многих задачах) аналоговое значение, меняется в небольших пределах,
то добавлен кэш ( rawValue --> calValue ) по умолчанию на 5 значений. Размер кэша можно задать
(поменять или отключить) при помощи Calibration::setCacheSize().
\note Слишком большим задавать кэш не рекомендуется, т.к. тогда поиск по кэшу будет сопоставим с поиском по диаграмме.
Помимо этого, с учётом того, что каждое попадание в кэш обновляет счётчик обращений к значению, необходимо
пересортировывать весь кэш (чтобы наиболее часто используемые были в начале). Чтобы не делать эту операцию каждый
раз, сделан счётчик циклов. Т.е. через какое количество обращений к кэшу, производить принудительную пересортировку.
Значение по умолчанию - 5(размер кэша). Задать можно при помощи Calibration::setCacheResortCycle()
*/ */
class Calibration class Calibration
{ {
...@@ -59,7 +68,7 @@ class Calibration ...@@ -59,7 +68,7 @@ class Calibration
typedef float TypeOfValue; typedef float TypeOfValue;
/*! выход за границы диапазона */ /*! выход за границы диапазона */
static const TypeOfValue outOfRange; static const long outOfRange;
/*! /*!
Получение калиброванного значения Получение калиброванного значения
...@@ -98,7 +107,6 @@ class Calibration ...@@ -98,7 +107,6 @@ class Calibration
/*! Возвращает крайнее правое значение 'y' встретившееся в диаграмме (ПОСЛЕ СОРТИРОВКИ ПО ВОЗРАСТАНИЮ 'x'!) */ /*! Возвращает крайнее правое значение 'y' встретившееся в диаграмме (ПОСЛЕ СОРТИРОВКИ ПО ВОЗРАСТАНИЮ 'x'!) */
inline long getRightRaw(){ return rightRaw; } inline long getRightRaw(){ return rightRaw; }
/*! построение характеристрики из конф. файла /*! построение характеристрики из конф. файла
\param name - название характеристики в файле \param name - название характеристики в файле
\param confile - файл содержащий данные \param confile - файл содержащий данные
...@@ -114,9 +122,17 @@ class Calibration ...@@ -114,9 +122,17 @@ class Calibration
return lround(val); 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 );
friend std::ostream& operator<<(std::ostream& os, Calibration* c ); friend std::ostream& operator<<(std::ostream& os, Calibration* c );
// ---------------------------------------------------------------
/*! точка характеристики */ /*! точка характеристики */
struct Point struct Point
{ {
...@@ -184,9 +200,42 @@ class Calibration ...@@ -184,9 +200,42 @@ class Calibration
long minRaw, maxRaw, minVal, maxVal, rightVal, leftVal, rightRaw, leftRaw; long minRaw, maxRaw, minVal, maxVal, rightVal, leftVal, rightRaw, leftRaw;
void insertToCache( const long raw, const long val );
private: private:
PartsVec pvec; PartsVec pvec;
std::string myname; 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_ #endif // Calibration_H_
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
using namespace std; using namespace std;
using namespace UniSetTypes; 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(): Calibration::Part::Part():
k(0) k(0)
...@@ -105,7 +105,11 @@ Calibration::TypeOfValue Calibration::Part::calcX( const TypeOfValue& y ) const ...@@ -105,7 +105,11 @@ Calibration::TypeOfValue Calibration::Part::calcX( const TypeOfValue& y ) const
Calibration::Calibration(): Calibration::Calibration():
minRaw(0),maxRaw(0),minVal(0),maxVal(0),rightVal(0),leftVal(0),rightRaw(0),leftRaw(0), minRaw(0),maxRaw(0),minVal(0),maxVal(0),rightVal(0),leftVal(0),rightRaw(0),leftRaw(0),
pvec(50), pvec(50),
myname("") myname(""),
szCache(5),
cache(5),
numCacheResort(5),
numCallToCache(5)
{ {
} }
...@@ -114,14 +118,22 @@ myname("") ...@@ -114,14 +118,22 @@ myname("")
Calibration::Calibration( const string& name, const string& confile ): Calibration::Calibration( const string& name, const string& confile ):
minRaw(0),maxRaw(0),minVal(0),maxVal(0),rightVal(0),leftVal(0),rightRaw(0),leftRaw(0), minRaw(0),maxRaw(0),minVal(0),maxVal(0),rightVal(0),leftVal(0),rightRaw(0),leftRaw(0),
pvec(50), pvec(50),
myname(name) myname(name),
szCache(5),
cache(5),
numCacheResort(5),
numCallToCache(5)
{ {
build(name,confile,0); build(name,confile,0);
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
Calibration::Calibration( xmlNode* node ): 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); UniXML_iterator it(node);
myname = it.getProp("name"); myname = it.getProp("name");
...@@ -214,7 +226,7 @@ void Calibration::build( const string& name, const string& confile, xmlNode* roo ...@@ -214,7 +226,7 @@ void Calibration::build( const string& name, const string& confile, xmlNode* roo
{ {
leftRaw = beg->left_x(); leftRaw = beg->left_x();
leftVal = beg->left_y(); leftVal = beg->left_y();
end--; --end;
rightRaw = end->right_x(); rightRaw = end->right_x();
rightVal = end->right_y(); rightVal = end->right_y();
} }
...@@ -257,18 +269,69 @@ long Calibration::getValue( long raw, bool crop_raw ) ...@@ -257,18 +269,69 @@ long Calibration::getValue( long raw, bool crop_raw )
if( raw > rightRaw ) if( raw > rightRaw )
return (crop_raw ? rightVal : outOfRange); 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()); PartsVec::iterator fit = find_range(raw, pvec.begin(), pvec.end());
if( fit == pvec.end() ) if( fit == pvec.end() )
{
if( szCache )
insertToCache(raw,outOfRange);
return outOfRange; return outOfRange;
}
TypeOfValue q = fit->getY(raw); TypeOfValue q = fit->getY(raw);
if( q != outOfRange ) if( q != outOfRange )
{
if( szCache )
insertToCache(raw, tRound(q) );
return tRound(q); return tRound(q);
}
if( szCache )
insertToCache(raw,outOfRange);
return 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 ) long Calibration::getRawValue( long cal, bool range )
{ {
for( PartsVec::iterator it=pvec.begin(); it!=pvec.end(); ++it ) for( PartsVec::iterator it=pvec.begin(); it!=pvec.end(); ++it )
......
...@@ -522,7 +522,13 @@ bool IOBase::initItem( IOBase* b, UniXML_iterator& it, SMInterface* shm, ...@@ -522,7 +522,13 @@ bool IOBase::initItem( IOBase* b, UniXML_iterator& it, SMInterface* shm,
std::string caldiagram( it.getProp("caldiagram") ); std::string caldiagram( it.getProp("caldiagram") );
if( !caldiagram.empty() ) if( !caldiagram.empty() )
{
b->cdiagram = UniSetExtensions::buildCalibrationDiagram(caldiagram); 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 ) 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