Merge pull request #5257 from t-miyamae/wip-mshec-fixlogic4

erasure code: shec performance optimization by decoding cache

Reviewed-by: Loic Dachary <ldachary@redhat.com>
This commit is contained in:
Loic Dachary 2015-09-08 13:52:05 +02:00
commit 49ee455b35
3 changed files with 311 additions and 22 deletions

View File

@ -562,6 +562,14 @@ int ErasureCodeShec::shec_make_decoding_matrix(bool prepare, int *want_, int *av
}
}
if (tcache.getDecodingTableFromCache(decoding_matrix,
dm_row, dm_column, minimum,
technique,
k, m, c, w,
want, avails)) {
return 0;
}
for (unsigned long long pp = 0; pp < (1ull << m); ++pp) {
// select parity chunks
@ -755,6 +763,9 @@ int ErasureCodeShec::shec_make_decoding_matrix(bool prepare, int *want_, int *av
int ret = jerasure_invert_matrix(tmpmat, decoding_matrix, mindup, w);
tcache.putDecodingTableToCache(decoding_matrix, dm_row, dm_column, minimum, technique,
k, m, c, w, want, avails);
return ret;
}

View File

@ -23,34 +23,95 @@
#include "common/debug.h"
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
#define dout_subsys ceph_subsys_osd
#undef dout_prefix
#define dout_prefix _tc_prefix(_dout)
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
static ostream&
_tc_prefix(std::ostream* _dout) {
return *_dout << "ErasureCodeShecTableCache: ";
}
// -----------------------------------------------------------------------------
ErasureCodeShecTableCache::~ErasureCodeShecTableCache()
{
Mutex::Locker lock(codec_tables_guard);
codec_technique_tables_t::const_iterator ttables_it;
codec_tables_t::const_iterator tables_it;
codec_tables_t_::const_iterator tables_it_;
codec_tables_t__::const_iterator tables_it__;
codec_table_t::const_iterator table_it;
// clean-up all allocated tables
{
codec_technique_tables_t::const_iterator ttables_it;
codec_tables_t::const_iterator tables_it;
codec_tables_t_::const_iterator tables_it_;
codec_tables_t__::const_iterator tables_it__;
codec_table_t::const_iterator table_it;
for (ttables_it = encoding_table.begin(); ttables_it != encoding_table.end(); ++ttables_it) {
for (tables_it = ttables_it->second.begin(); tables_it != ttables_it->second.end(); ++tables_it) {
for (tables_it_ = tables_it->second.begin(); tables_it_ != tables_it->second.end(); ++tables_it_) {
for (tables_it__ = tables_it_->second.begin(); tables_it__ != tables_it_->second.end(); ++tables_it__) {
for (table_it = tables_it__->second.begin(); table_it != tables_it__->second.end(); ++table_it) {
if (table_it->second) {
if (*(table_it->second)) {
delete *(table_it->second);
}
delete table_it->second;
}
}
for (ttables_it = encoding_table.begin(); ttables_it != encoding_table.end(); ++ttables_it) {
for (tables_it = ttables_it->second.begin(); tables_it != ttables_it->second.end(); ++tables_it) {
for (tables_it_ = tables_it->second.begin(); tables_it_ != tables_it->second.end(); ++tables_it_) {
for (tables_it__ = tables_it_->second.begin(); tables_it__ != tables_it_->second.end(); ++tables_it__) {
for (table_it = tables_it__->second.begin(); table_it != tables_it__->second.end(); ++table_it) {
if (table_it->second) {
if (*(table_it->second)) {
delete *(table_it->second);
}
delete table_it->second;
}
}
}
}
}
}
}
{
std::map<int, lru_map_t*>::const_iterator lru_map_it;
std::map<int, lru_list_t*>::const_iterator lru_list_it;
for (lru_map_it = decoding_tables.begin();
lru_map_it != decoding_tables.end();
++lru_map_it) {
if (lru_map_it->second) {
delete lru_map_it->second;
}
}
for (lru_list_it = decoding_tables_lru.begin();
lru_list_it != decoding_tables_lru.end();
++lru_list_it) {
if (lru_list_it->second) {
delete lru_list_it->second;
}
}
}
}
ErasureCodeShecTableCache::lru_map_t*
ErasureCodeShecTableCache::getDecodingTables(int technique) {
// the caller must hold the guard mutex:
// => Mutex::Locker lock(codec_tables_guard);
// create an lru_map if not yet allocated
if (!decoding_tables[technique]) {
decoding_tables[technique] = new lru_map_t;
}
return decoding_tables[technique];
}
ErasureCodeShecTableCache::lru_list_t*
ErasureCodeShecTableCache::getDecodingTablesLru(int technique) {
// the caller must hold the guard mutex:
// => Mutex::Locker lock(codec_tables_guard);
// create an lru_list if not yet allocated
if (!decoding_tables_lru[technique]) {
decoding_tables_lru[technique] = new lru_list_t;
}
return decoding_tables_lru[technique];
}
int**
@ -95,3 +156,162 @@ ErasureCodeShecTableCache::getLock()
{
return &codec_tables_guard;
}
uint64_t
ErasureCodeShecTableCache::getDecodingCacheSignature(int k, int m, int c, int w,
int *erased, int *avails) {
uint64_t signature = 0;
signature = (uint64_t)k;
signature |= ((uint64_t)m << 6);
signature |= ((uint64_t)c << 12);
signature |= ((uint64_t)w << 18);
for (int i=0; i < k+m; i++) {
signature |= ((uint64_t)(avails[i] ? 1 : 0) << (24+i));
}
for (int i=0; i < k+m; i++) {
signature |= ((uint64_t)(erased[i] ? 1 : 0) << (44+i));
}
return signature;
}
bool
ErasureCodeShecTableCache::getDecodingTableFromCache(int* decoding_matrix,
int* dm_row,
int* dm_column,
int* minimum,
int technique,
int k,
int m,
int c,
int w,
int* erased,
int* avails) {
// --------------------------------------------------------------------------
// LRU decoding matrix cache
// --------------------------------------------------------------------------
uint64_t signature = getDecodingCacheSignature(k, m, c, w, erased, avails);
Mutex::Locker lock(codec_tables_guard);
dout(20) << "[ get table ] = " << signature << dendl;
// we try to fetch a decoding table from an LRU cache
lru_map_t* decode_tbls_map =
getDecodingTables(technique);
lru_list_t* decode_tbls_lru =
getDecodingTablesLru(technique);
lru_map_t::iterator decode_tbls_map_it = decode_tbls_map->find(signature);
if (decode_tbls_map_it == decode_tbls_map->end()) {
return false;
}
dout(20) << "[ cached table ] = " << signature << dendl;
// copy parameters out of the cache
memcpy(decoding_matrix,
decode_tbls_map_it->second.second.decoding_matrix,
k * k * sizeof(int));
memcpy(dm_row,
decode_tbls_map_it->second.second.dm_row,
k * sizeof(int));
memcpy(dm_column,
decode_tbls_map_it->second.second.dm_column,
k * sizeof(int));
memcpy(minimum,
decode_tbls_map_it->second.second.minimum,
(k+m) * sizeof(int));
// find item in LRU queue and push back
decode_tbls_lru->splice(decode_tbls_lru->end(),
*decode_tbls_lru,
decode_tbls_map_it->second.first);
return true;
}
void
ErasureCodeShecTableCache::putDecodingTableToCache(int* decoding_matrix,
int* dm_row,
int* dm_column,
int* minimum,
int technique,
int k,
int m,
int c,
int w,
int* erased,
int* avails) {
// --------------------------------------------------------------------------
// LRU decoding matrix cache
// --------------------------------------------------------------------------
Mutex::Locker lock(codec_tables_guard);
uint64_t signature = getDecodingCacheSignature(k, m, c, w, erased, avails);
dout(20) << "[ put table ] = " << signature << dendl;
// we store a new table to the cache
// bufferptr cachetable;
lru_map_t* decode_tbls_map =
getDecodingTables(technique);
lru_list_t* decode_tbls_lru =
getDecodingTablesLru(technique);
if (decode_tbls_map->count(signature)) {
dout(20) << "[ already on table ] = " << signature << dendl;
// find item in LRU queue and push back
decode_tbls_lru->splice(decode_tbls_lru->end(),
*decode_tbls_lru,
(*decode_tbls_map)[signature].first);
return;
}
// evt. shrink the LRU queue/map
if ((int)decode_tbls_lru->size() >=
ErasureCodeShecTableCache::decoding_tables_lru_length) {
dout(20) << "[ shrink lru ] = " << signature << dendl;
// remove from map
decode_tbls_map->erase(decode_tbls_lru->front());
// remove from lru
decode_tbls_lru->pop_front();
}
{
dout(20) << "[ store table ] = " << signature << dendl;
decode_tbls_lru->push_back(signature);
// allocate a new buffer
lru_list_t::iterator it_end = decode_tbls_lru->end();
it_end--;
lru_entry_t &map_value =
(*decode_tbls_map)[signature] =
std::make_pair(it_end, DecodingCacheParameter());
map_value.second.decoding_matrix = new int[k*k];
map_value.second.dm_row = new int[k];
map_value.second.dm_column = new int[k];
map_value.second.minimum = new int[k+m];
memcpy(map_value.second.decoding_matrix,
decoding_matrix,
k * k * sizeof(int));
memcpy(map_value.second.dm_row,
dm_row,
k * sizeof(int));
memcpy(map_value.second.dm_column,
dm_column,
k * sizeof(int));
memcpy(map_value.second.minimum,
minimum,
(k+m) * sizeof(int));
dout(20) << "[ cache size ] = " << decode_tbls_lru->size() << dendl;
}
}

View File

@ -31,11 +31,43 @@ class ErasureCodeShecTableCache {
// ---------------------------------------------------------------------------
// This class implements a table cache for encoding and decoding matrices.
// Encoding matrices are shared for the same (k,m,c,w) combination.
// It supplies a decoding matrix lru cache which is shared for identical
// matrix types e.g. there is one cache (lru-list + lru-map)
// ---------------------------------------------------------------------------
class DecodingCacheParameter {
public:
int* decoding_matrix; // size: k*k
int* dm_row; // size: k
int* dm_column; // size: k
int* minimum; // size: k+m
DecodingCacheParameter() {
decoding_matrix = 0;
dm_row = 0;
dm_column = 0;
minimum = 0;
}
~DecodingCacheParameter() {
if (decoding_matrix) {
delete[] decoding_matrix;
}
if (dm_row) {
delete[] dm_row;
}
if (dm_column) {
delete[] dm_column;
}
if (minimum) {
delete[] minimum;
}
}
};
public:
typedef std::pair<std::list<std::string>::iterator, bufferptr> lru_entry_t;
static const int decoding_tables_lru_length = 10000;
typedef std::pair<std::list<uint64_t>::iterator,
DecodingCacheParameter> lru_entry_t;
typedef std::map< int, int** > codec_table_t;
typedef std::map< int, codec_table_t > codec_tables_t__;
typedef std::map< int, codec_tables_t__ > codec_tables_t_;
@ -43,6 +75,9 @@ class ErasureCodeShecTableCache {
typedef std::map< int, codec_tables_t > codec_technique_tables_t;
// int** matrix = codec_technique_tables_t[technique][k][m][c][w]
typedef std::map< uint64_t, lru_entry_t > lru_map_t;
typedef std::list< uint64_t > lru_list_t;
ErasureCodeShecTableCache() :
codec_tables_guard("shec-lru-cache")
{
@ -52,15 +87,38 @@ class ErasureCodeShecTableCache {
Mutex codec_tables_guard; // mutex used to protect modifications in encoding/decoding table maps
bool getDecodingTableFromCache(int* matrix,
int* dm_row, int* dm_column,
int* minimum,
int technique,
int k, int m, int c, int w,
int* want, int* avails);
void putDecodingTableToCache(int* matrix,
int* dm_row, int* dm_column,
int* minimum,
int technique,
int k, int m, int c, int w,
int* want, int* avails);
int** getEncodingTable(int technique, int k, int m, int c, int w);
int** getEncodingTableNoLock(int technique, int k, int m, int c, int w);
int* setEncodingTable(int technique, int k, int m, int c, int w, int*);
private:
codec_technique_tables_t encoding_table; // encoding coefficients accessed via table[technique][k][m]
// encoding table accessed via table[matrix][k][m][c][w]
// decoding table cache accessed via map[matrixtype]
// decoding table lru list accessed via list[matrixtype]
codec_technique_tables_t encoding_table;
std::map<int, lru_map_t*> decoding_tables;
std::map<int, lru_list_t*> decoding_tables_lru;
lru_map_t* getDecodingTables(int technique);
lru_list_t* getDecodingTablesLru(int technique);
uint64_t getDecodingCacheSignature(int k, int m, int c, int w,
int *want, int *avails);
Mutex* getLock();
};
#endif