Further work on vectorization. Works but not yet finished.

This commit is contained in:
Couriersud 2014-05-29 14:03:07 +00:00
parent d17e376dc6
commit f27ccb3303
4 changed files with 194 additions and 146 deletions

View File

@ -41,7 +41,7 @@ ATTR_COLD void netlist_matrix_solver_t::setup(netlist_analog_net_t::list_t &nets
for (int k = 0; k < nets.count(); k++)
{
m_nets.add(net_entry(nets[k]));
m_nets.add(nets[k]);
}
for (int k = 0; k < nets.count(); k++)
@ -80,11 +80,13 @@ ATTR_COLD void netlist_matrix_solver_t::setup(netlist_analog_net_t::list_t &nets
netlist_terminal_t *pterm = dynamic_cast<netlist_terminal_t *>(p);
// for gauss seidel
pterm->m_new_analog_ptr = &pterm->m_otherterm->net().as_analog().m_new_Analog;
#if 0
if (pterm->m_otherterm->net().isRailNet())
m_nets[k].m_rails.add(pterm);
else
m_nets[k].m_terms.add(pterm);
#endif
add_term(k, pterm);
}
NL_VERBOSE_OUT(("Added terminal\n"));
break;
@ -139,7 +141,7 @@ ATTR_HOT double netlist_matrix_solver_direct_t<m_N, _storage_N>::compute_next_ti
#else
for (int k = 0; k < N(); k++)
{
netlist_analog_net_t *n = m_nets[k].m_net;
netlist_analog_net_t *n = m_nets[k];
#endif
double DD_n = (n->m_cur_Analog - n->m_last_Analog);
@ -190,7 +192,7 @@ ATTR_HOT void netlist_matrix_solver_t::update_inputs()
#if 1
for (int k = 0; k < m_nets.count(); k++)
{
netlist_analog_net_t *p= m_nets[k].m_net;
netlist_analog_net_t *p= m_nets[k];
p->m_last_Analog = p->m_cur_Analog;
}
#else
@ -323,19 +325,51 @@ void netlist_matrix_solver_gauss_seidel_t<m_N, _storage_N>::log_stats()
ATTR_COLD int netlist_matrix_solver_t::get_net_idx(netlist_net_t *net)
{
for (int k = 0; k < m_nets.count(); k++)
if (m_nets[k].m_net == net)
if (m_nets[k] == net)
return k;
return -1;
}
template <int m_N, int _storage_N>
ATTR_COLD void netlist_matrix_solver_direct_t<m_N, _storage_N>::add_term(int k, netlist_terminal_t *term)
{
if (term->m_otherterm->net().isRailNet())
{
//m_nets[k].m_rails.add(pterm);
m_rails[k].add(terms_t(term, -1));
}
else
{
int ot = get_net_idx(&term->m_otherterm->net());
if (ot>=0)
{
m_terms[k].add(terms_t(term, ot));
SOLVER_VERBOSE_OUT(("Net %d Term %s %f %f\n", k, terms[i]->name().cstr(), terms[i]->m_gt, terms[i]->m_go));
}
/* Should this be allowed ? */
else // if (ot<0)
{
m_rails[k].add(terms_t(term, ot));
netlist().error("found term with missing othernet %s\n", term->name().cstr());
}
}
}
template <int m_N, int _storage_N>
ATTR_COLD void netlist_matrix_solver_direct_t<m_N, _storage_N>::vsetup(netlist_analog_net_t::list_t &nets)
{
m_dim = nets.count();
for (int k = 0; k < N(); k++)
{
m_terms[k].clear();
m_rails[k].clear();
}
netlist_matrix_solver_t::setup(nets);
m_terms.clear();
m_rail_start = 0;
#if 0
for (int k = 0; k < N(); k++)
{
const netlist_terminal_t::list_t &terms = m_nets[k].m_terms;
@ -344,31 +378,38 @@ ATTR_COLD void netlist_matrix_solver_direct_t<m_N, _storage_N>::vsetup(netlist_a
int ot = get_net_idx(&terms[i]->m_otherterm->net());
if (ot>=0)
{
m_terms.add(terms_t(terms[i], k, ot));
m_terms[k].add(terms_t(terms[i], ot));
SOLVER_VERBOSE_OUT(("Net %d Term %s %f %f\n", k, terms[i]->name().cstr(), terms[i]->m_gt, terms[i]->m_go));
}
}
}
m_rail_start = m_terms.count();
/* Should this be allowed ? */
for (int k = 0; k < N(); k++)
{
const netlist_terminal_t::list_t &terms = m_nets[k].m_terms;
const netlist_terminal_t::list_t &rails = m_nets[k].m_rails;
for (int i = 0; i < terms.count(); i++)
{
int ot = get_net_idx(&terms[i]->m_otherterm->net());
if (ot<0)
{
m_terms.add(terms_t(terms[i], k, ot));
m_rails[k].add(terms_t(terms[i], ot));
netlist().warning("found term with missing othernet %s\n", terms[i]->name().cstr());
}
}
}
for (int k = 0; k < N(); k++)
{
const netlist_terminal_t::list_t &rails = m_nets[k].m_rails;
for (int i = 0; i < rails.count(); i++)
{
m_terms.add(terms_t(rails[i], k, -1));
m_rails[k].add(terms_t(rails[i], -1));
SOLVER_VERBOSE_OUT(("Net %d Rail %s %f %f\n", k, rails[i]->name().cstr(), rails[i]->m_gt, rails[i]->m_go));
}
}
#endif
}
template <int m_N, int _storage_N>
@ -378,43 +419,35 @@ ATTR_HOT void netlist_matrix_solver_direct_t<m_N, _storage_N>::build_LE()
for (int i=0; i < _storage_N; i++)
m_A[k][i] = 0.0;
for (int k=0; k < _storage_N; k++)
m_RHS[k] = 0.0;
#if 0
for (int k = 0; k < N(); k++)
{
double rhsk = 0.0;
double akk = 0.0;
const int terms_count = m_terms[k].count();
const terms_t *terms = m_terms[k];
for (int i = 0; i < m_term_num; i++)
for (int i = 0; i < terms_count; i++)
{
terms_t &t = m_terms[i];
m_RHS[t.m_net_this] += t.m_term->m_Idr;
m_A[t.m_net_this][t.m_net_this] += t.m_term->m_gt;
if (t.m_net_other >= 0)
{
//m_A[t.net_other][t.net_other] += t.term->m_otherterm->m_gt;
m_A[t.m_net_this][t.m_net_other] += -t.m_term->m_go;
//m_A[t.net_other][t.net_this] += -t.term->m_otherterm->m_go;
}
else
m_RHS[t.m_net_this] += t.m_term->m_go * t.m_term->m_otherterm->net().as_analog().Q_Analog();
}
#else
for (int i = 0; i < m_rail_start; i++)
{
const terms_t &t = m_terms[i];
//printf("A %d %d %s %f %f\n",t.net_this, t.net_other, t.term->name().cstr(), t.term->m_gt, t.term->m_go);
m_RHS[t.m_net_this] += t.m_term->m_Idr;
m_A[t.m_net_this][t.m_net_this] += t.m_term->m_gt;
m_A[t.m_net_this][t.m_net_other] += -t.m_term->m_go;
rhsk = rhsk + terms[i].m_term->m_Idr;
akk = akk + terms[i].m_term->m_gt;
m_A[k][terms[i].m_net_other] += -terms[i].m_term->m_go;
}
for (int i = m_rail_start; i < m_terms.count(); i++)
{
const terms_t &t = m_terms[i];
m_RHS[t.m_net_this] += t.m_term->m_Idr;
m_A[t.m_net_this][t.m_net_this] += t.m_term->m_gt;
m_RHS[t.m_net_this] += t.m_term->m_go * t.m_term->m_otherterm->net().as_analog().Q_Analog();
const int rails_count = m_rails[k].count();
const terms_t *rails = m_rails[k];
for (int i = 0; i < rails_count; i++)
{
const terms_t t = rails[i];
rhsk = rhsk + t.m_term->m_Idr + t.m_term->m_go * t.m_term->m_otherterm->net().as_analog().Q_Analog();
akk = akk + t.m_term->m_gt;
}
m_RHS[k] = rhsk;
m_A[k][k] += akk;
}
#endif
}
template <int m_N, int _storage_N>
@ -504,7 +537,7 @@ ATTR_HOT double netlist_matrix_solver_direct_t<m_N, _storage_N>::delta(
double cerr2 = 0;
for (int i = 0; i < this->N(); i++)
{
const double e = (V[i] - this->m_nets[i].m_net->m_cur_Analog);
const double e = (V[i] - this->m_nets[i]->m_cur_Analog);
const double e2 = (m_RHS[i] - this->m_last_RHS[i]);
cerr = (fabs(e) > cerr ? fabs(e) : cerr);
cerr2 = (fabs(e2) > cerr2 ? fabs(e2) : cerr2);
@ -519,7 +552,7 @@ ATTR_HOT void netlist_matrix_solver_direct_t<m_N, _storage_N>::store(
{
for (int i = 0; i < this->N(); i++)
{
this->m_nets[i].m_net->m_cur_Analog = this->m_nets[i].m_net->m_new_Analog = V[i];
this->m_nets[i]->m_cur_Analog = this->m_nets[i]->m_new_Analog = V[i];
}
if (store_RHS)
{
@ -569,7 +602,7 @@ ATTR_HOT int netlist_matrix_solver_direct_t<m_N, _storage_N>::vsolve_non_dynamic
ATTR_HOT int netlist_matrix_solver_direct1_t::vsolve_non_dynamic()
{
netlist_analog_net_t *net = m_nets[0].m_net;
netlist_analog_net_t *net = m_nets[0];
this->build_LE();
//NL_VERBOSE_OUT(("%f %f\n", new_val, m_RHS[0] / m_A[0][0]);
@ -646,7 +679,7 @@ ATTR_HOT int netlist_matrix_solver_gauss_seidel_t<m_N, _storage_N>::vsolve_non_d
for (int k = 0; k < iN; k++)
{
new_v[k] = this->m_nets[k].m_net->m_cur_Analog;
new_v[k] = this->m_nets[k]->m_cur_Analog;
}
do {
resched = false;
@ -708,7 +741,7 @@ ATTR_HOT int netlist_matrix_solver_gauss_seidel_t<m_N, _storage_N>::vsolve_non_d
for (int k = 0; k < iN; k++)
{
this->m_nets[k].m_net->m_new_Analog = this->m_nets[k].m_net->m_cur_Analog;
this->m_nets[k]->m_new_Analog = this->m_nets[k]->m_cur_Analog;
}
for (int k = 0; k < iN; k++)
@ -717,25 +750,26 @@ ATTR_HOT int netlist_matrix_solver_gauss_seidel_t<m_N, _storage_N>::vsolve_non_d
double gabs_t = 0.0;
double RHS_t = 0.0;
//const netlist_analog_net_t &net = *this->m_nets[k];
const netlist_terminal_t::list_t &terms = this->m_nets[k].m_terms;
const netlist_terminal_t::list_t &rails = this->m_nets[k].m_rails;
const typename netlist_matrix_solver_direct_t<m_N, _storage_N>::xlist_t &terms = this->m_terms[k];
const typename netlist_matrix_solver_direct_t<m_N, _storage_N>::xlist_t &rails = this->m_rails[k];
const int term_count = terms.count();
const int rail_count = rails.count();
for (int i = 0; i < rail_count; i++)
{
gtot_t += rails[i]->m_gt;
gabs_t += fabs(rails[i]->m_go);
RHS_t += rails[i]->m_Idr;
RHS_t += rails[i]->m_go * rails[i]->m_otherterm->net().as_analog().Q_Analog();
const netlist_terminal_t *rail = rails[i].m_term;
gtot_t += rail->m_gt;
gabs_t += fabs(rail->m_go);
RHS_t += rail->m_Idr;
RHS_t += rail->m_go * rail->m_otherterm->net().as_analog().Q_Analog();
}
for (int i = 0; i < term_count; i++)
{
gtot_t += terms[i]->m_gt;
gabs_t += fabs(terms[i]->m_go);
RHS_t += terms[i]->m_Idr;
const netlist_terminal_t *term = terms[i].m_term;
gtot_t += term->m_gt;
gabs_t += fabs(term->m_go);
RHS_t += term->m_Idr;
}
gabs_t *= 1.0;
@ -760,13 +794,13 @@ ATTR_HOT int netlist_matrix_solver_gauss_seidel_t<m_N, _storage_N>::vsolve_non_d
for (int k = 0; k < iN; k++)
{
netlist_analog_net_t & RESTRICT net = *this->m_nets[k].m_net;
const netlist_terminal_t::list_t &terms = this->m_nets[k].m_terms;
netlist_analog_net_t & RESTRICT net = *this->m_nets[k];
const typename netlist_matrix_solver_direct_t<m_N, _storage_N>::xlist_t &terms = this->m_terms[k];
const int term_count = terms.count();
double Idrive = 0;
for (int i = 0; i < term_count; i++)
Idrive += terms[i]->m_go * *(terms[i]->m_new_analog_ptr);
Idrive += terms[i].m_term->m_go * *(terms[i].m_term->m_new_analog_ptr);
//double new_val = (net->m_cur_Analog * gabs[k] + iIdr) / (gtot[k]);
const double new_val = net.m_new_Analog * one_m_w[k] + (Idrive + RHS[k]) * w[k];
@ -796,7 +830,7 @@ ATTR_HOT int netlist_matrix_solver_gauss_seidel_t<m_N, _storage_N>::vsolve_non_d
this->m_calculations++;
for (int k = 0; k < this->N(); k++)
this->m_nets[k].m_net->m_cur_Analog = this->m_nets[k].m_net->m_new_Analog;
this->m_nets[k]->m_cur_Analog = this->m_nets[k]->m_new_Analog;
return resched_cnt;
}
@ -906,11 +940,29 @@ NETLIB_UPDATE(solver)
}
}
template <int m_N, int _storage_N>
netlist_matrix_solver_t * NETLIB_NAME(solver)::create_solver(const int gs_threshold, const bool use_specific)
{
if (use_specific && m_N == 1)
return new netlist_matrix_solver_direct1_t();
else if (use_specific && m_N == 2)
return new netlist_matrix_solver_direct2_t();
else
{
if (_storage_N >= gs_threshold)
return new netlist_matrix_solver_gauss_seidel_t<m_N,_storage_N>();
else
return new netlist_matrix_solver_direct_t<m_N, _storage_N>();
}
}
ATTR_COLD void NETLIB_NAME(solver)::post_start()
{
netlist_analog_net_t::list_t groups[100];
int cur_group = -1;
// FIXME: Turn into parameters ...
const int gs_threshold = 5;
const bool use_specific = true;
m_params.m_accuracy = m_accuracy.Value();
m_params.m_gs_loops = m_gs_loops.Value();
@ -956,53 +1008,42 @@ ATTR_COLD void NETLIB_NAME(solver)::post_start()
switch (net_count)
{
#if 1
case 1:
ms = new netlist_matrix_solver_direct1_t();
ms = create_solver<1,1>(gs_threshold, use_specific);
break;
case 2:
ms = new netlist_matrix_solver_direct2_t();
ms = create_solver<2,2>(gs_threshold, use_specific);
break;
case 3:
ms = new netlist_matrix_solver_direct_t<3,3>();
//ms = new netlist_matrix_solver_gauss_seidel_t<3,3>();
ms = create_solver<3,3>(gs_threshold, use_specific);
break;
case 4:
ms = new netlist_matrix_solver_direct_t<4,4>();
//ms = new netlist_matrix_solver_gauss_seidel_t<4,4>();
ms = create_solver<4,4>(gs_threshold, use_specific);
break;
case 5:
ms = new netlist_matrix_solver_direct_t<5,5>();
//ms = new netlist_matrix_solver_gauss_seidel_t<5,5>();
ms = create_solver<5,5>(gs_threshold, use_specific);
break;
case 6:
ms = new netlist_matrix_solver_direct_t<6,6>();
//ms = new netlist_matrix_solver_gauss_seidel_t<6,6>();
ms = create_solver<6,6>(gs_threshold, use_specific);
break;
case 7:
//ms = new netlist_matrix_solver_direct_t<6,6>();
ms = new netlist_matrix_solver_gauss_seidel_t<7,7>();
ms = create_solver<7,7>(gs_threshold, use_specific);
break;
case 8:
//ms = new netlist_matrix_solver_direct_t<6,6>();
ms = new netlist_matrix_solver_gauss_seidel_t<8,8>();
ms = create_solver<8,8>(gs_threshold, use_specific);
break;
#endif
default:
if (net_count <= 16)
{
//ms = new netlist_matrix_solver_direct_t<0,16>();
ms = new netlist_matrix_solver_gauss_seidel_t<0,16>();
ms = create_solver<0,16>(gs_threshold, use_specific);
}
else if (net_count <= 32)
{
//ms = new netlist_matrix_solver_direct_t<0,16>();
ms = new netlist_matrix_solver_gauss_seidel_t<0,32>();
ms = create_solver<0,32>(gs_threshold, use_specific);
}
else if (net_count <= 64)
{
//ms = new netlist_matrix_solver_direct_t<0,16>();
ms = new netlist_matrix_solver_gauss_seidel_t<0,64>();
ms = create_solver<0,64>(gs_threshold, use_specific);
}
else
{

View File

@ -9,6 +9,9 @@
#include "../nl_setup.h"
#include "../nl_base.h"
//#define ATTR_ALIGNED(N) __attribute__((aligned(N)))
#define ATTR_ALIGNED(N) ATTR_ALIGN
// ----------------------------------------------------------------------------------------
// Macros
// ----------------------------------------------------------------------------------------
@ -37,7 +40,7 @@ struct netlist_solver_parameters_t
netlist_time m_nt_sync_delay;
};
class netlist_matrix_solver_t : public netlist_device_t
class ATTR_ALIGNED(64) netlist_matrix_solver_t : public netlist_device_t
{
public:
typedef plinearlist_t<netlist_matrix_solver_t *> list_t;
@ -67,40 +70,15 @@ public:
protected:
class net_entry
{
public:
net_entry(netlist_analog_net_t *net) : m_net(net) {}
net_entry() : m_net(NULL) {}
net_entry(const net_entry &rhs)
{
m_net = rhs.m_net;
m_terms = rhs.m_terms;
m_rails = rhs.m_rails;
}
net_entry &operator=(const net_entry &rhs)
{
m_net = rhs.m_net;
m_terms = rhs.m_terms;
m_rails = rhs.m_rails;
return *this;
}
netlist_analog_net_t * RESTRICT m_net;
netlist_terminal_t::list_t m_terms;
netlist_terminal_t::list_t m_rails;
};
ATTR_COLD void setup(netlist_analog_net_t::list_t &nets);
// return true if a reschedule is needed ...
ATTR_HOT virtual int vsolve_non_dynamic() = 0;
ATTR_COLD virtual void add_term(int net_idx, netlist_terminal_t *term) = 0;
int m_calculations;
plinearlist_t<net_entry> m_nets;
plinearlist_t<netlist_analog_net_t *> m_nets;
plinearlist_t<netlist_analog_output_t *> m_inps;
private:
@ -126,14 +104,13 @@ private:
};
template <int m_N, int _storage_N>
class netlist_matrix_solver_direct_t: public netlist_matrix_solver_t
class ATTR_ALIGNED(64) netlist_matrix_solver_direct_t: public netlist_matrix_solver_t
{
public:
netlist_matrix_solver_direct_t()
: netlist_matrix_solver_t()
, m_dim(0)
, m_rail_start(0)
{}
virtual ~netlist_matrix_solver_direct_t() {}
@ -144,6 +121,8 @@ public:
ATTR_HOT inline const int N() const { if (m_N == 0) return m_dim; else return m_N; }
protected:
ATTR_COLD virtual void add_term(int net_idx, netlist_terminal_t *term);
ATTR_HOT virtual int vsolve_non_dynamic();
ATTR_HOT int solve_non_dynamic();
ATTR_HOT inline void build_LE();
@ -154,31 +133,35 @@ protected:
ATTR_HOT virtual double compute_next_timestep(const double);
double m_A[_storage_N][_storage_N];
double m_RHS[_storage_N];
double m_last_RHS[_storage_N]; // right hand side - contains currents
ATTR_ALIGNED(64) double m_A[_storage_N][_storage_N];
ATTR_ALIGNED(64) double m_RHS[_storage_N];
ATTR_ALIGNED(64) double m_last_RHS[_storage_N]; // right hand side - contains currents
struct terms_t{
struct ATTR_ALIGNED(64) terms_t{
terms_t(netlist_terminal_t *term, int net_this, int net_other)
: m_term(term), m_net_this(net_this), m_net_other(net_other)
terms_t(netlist_terminal_t *term, int net_other)
: m_term(term), m_net_other(net_other)
{}
terms_t()
: m_term(NULL), m_net_this(-1), m_net_other(-1)
: m_term(NULL), m_net_other(-1)
{}
netlist_terminal_t * RESTRICT m_term;
int m_net_this;
ATTR_ALIGNED(64) netlist_terminal_t ATTR_ALIGNED(64) * RESTRICT m_term;
int m_net_other;
};
typedef plinearlist_t<terms_t> xlist_t;
xlist_t m_terms[_storage_N];
xlist_t m_rails[_storage_N];
plinearlist_t<double> xx[_storage_N];
private:
int m_dim;
int m_rail_start;
plinearlist_t<terms_t> m_terms;
};
template <int m_N, int _storage_N>
class netlist_matrix_solver_gauss_seidel_t: public netlist_matrix_solver_direct_t<m_N, _storage_N>
class ATTR_ALIGNED(64) netlist_matrix_solver_gauss_seidel_t: public netlist_matrix_solver_direct_t<m_N, _storage_N>
{
public:
@ -201,22 +184,39 @@ private:
};
class netlist_matrix_solver_direct1_t: public netlist_matrix_solver_direct_t<1,1>
class ATTR_ALIGNED(64) netlist_matrix_solver_direct1_t: public netlist_matrix_solver_direct_t<1,1>
{
protected:
ATTR_HOT int vsolve_non_dynamic();
private:
};
class netlist_matrix_solver_direct2_t: public netlist_matrix_solver_direct_t<2,2>
class ATTR_ALIGNED(64) netlist_matrix_solver_direct2_t: public netlist_matrix_solver_direct_t<2,2>
{
protected:
ATTR_HOT int vsolve_non_dynamic();
private:
};
NETLIB_DEVICE_WITH_PARAMS(solver,
typedef netlist_core_device_t::list_t dev_list_t;
class ATTR_ALIGNED(64) NETLIB_NAME(solver) : public netlist_device_t
{
public:
NETLIB_NAME(solver)()
: netlist_device_t() { }
ATTR_COLD virtual ~NETLIB_NAME(solver)();
ATTR_COLD void post_start();
ATTR_HOT inline double gmin() { return m_gmin.Value(); }
protected:
ATTR_HOT void update();
ATTR_HOT void start();
ATTR_HOT void reset();
ATTR_HOT void update_param();
//typedef netlist_core_device_t::list_t dev_list_t;
netlist_ttl_input_t m_fb_step;
netlist_ttl_output_t m_Q_step;
@ -234,17 +234,14 @@ NETLIB_DEVICE_WITH_PARAMS(solver,
netlist_param_int_t m_parallel;
netlist_matrix_solver_t::list_t m_mat_solvers;
public:
ATTR_COLD virtual ~NETLIB_NAME(solver)();
ATTR_COLD void post_start();
ATTR_HOT inline double gmin() { return m_gmin.Value(); }
private:
netlist_solver_parameters_t m_params;
);
template <int m_N, int _storage_N>
netlist_matrix_solver_t *create_solver(int gs_threshold, bool use_specific);
};
#endif /* NLD_SOLVER_H_ */

View File

@ -424,7 +424,7 @@ private:
NETLIST_SAVE_TYPE(netlist_core_terminal_t::state_e, DT_INT);
class netlist_terminal_t : public netlist_core_terminal_t
class ATTR_ALIGN netlist_terminal_t : public netlist_core_terminal_t
{
NETLIST_PREVENT_COPYING(netlist_terminal_t)
public:

View File

@ -64,6 +64,19 @@ public:
m_list = NULL;
}
ATTR_HOT inline operator _ListClass * () { return m_list; }
ATTR_HOT inline operator const _ListClass * const () { return m_list; }
/* using the [] operator will not allow gcc to vectorize code because
* basically a pointer is returned.
* array works around this.
*/
ATTR_HOT inline _ListClass *array() { return m_list; }
ATTR_HOT inline _ListClass& operator[](const int index) { return m_list[index]; }
ATTR_HOT inline const _ListClass& operator[](const int index) const { return m_list[index]; }
ATTR_HOT inline void add(const _ListClass &elem)
{
if (m_count >= m_num_elements){
@ -140,9 +153,6 @@ public:
clear();
}
ATTR_HOT inline _ListClass& operator[](const int & index) { return m_list[index]; }
ATTR_HOT inline const _ListClass& operator[](const int & index) const { return m_list[index]; }
private:
ATTR_HOT inline void resize(const int new_size)
{