Краткое описание происходящего:
Цель - обобщить некоторый код, который у меня есть. Короче говоря, существует базовый класс base
, который управляет std::array<unsigned long long,N_DIM_IDX>
. Классы строятся на классах, которые строятся на классах ... основываются на base
. У классов есть методы, которые выполняют много проверок для установленных битов, сдвигают и переключают биты и подсчитывают установленные биты base
. std::array
в основном распространяется за пределы 64-битных коллекций. Как он расширяется и отслеживает конечные позиции, и такие вещи заботятся макросами.
Каждый раз, когда мне нужен новый прогон, мне нужно менять макросы. На самом деле мне нужно изменить один макрос, который устанавливает все макросы. Я не могу перейти с unsigned long long
, потому что весь бухгалтерский учет был сделан для 64-битных модулей, и я использовал ULL
для литералов в нескольких местах. Я подумываю заменить все это static constexpr
членами из шаблонной структуры и сделать возможным использование любого unsigned
в качестве строительного блока, а не только ull
Это то, что я подумываю заменить:
using myuint = unsigned long long;
// Only reset this for new runs if needed:
#define BASE_DIM 120ULL
#define DIM 64ULL
#if BASE_DIM%DIM==0ULL
#define N_DIM_IDX ((BASE_DIM)/(DIM))
#define POS_LAST 63ULL
#define POS_LAST_IDX (N_DIM_IDX - 1ULL)
#else
#define N_DIM_IDX ( 1ULL + ((BASE_DIM)/(DIM)) )
#define POS_LAST ((BASE_DIM%DIM) - 1ULL)
#define POS_LAST_IDX (N_DIM_IDX - 1ULL)
#endif
Теперь они встроены в бесчисленные места кода, в критически важные части, где важна скорость. Вот что я рассматриваю в качестве замены:
// size in bits. maybe change it as all platform don't necessarily have byte = 8 bits
template<typename U, std::enable_if_t<std::is_unsigned<U>::value, int> = 0 >
struct T_bit_size{
typedef U type;
static constexpr U value = sizeof(U)*8;
};
template<typename U, U D, typename E = void >
struct details{
static constexpr bool value = false;
static constexpr bool divisible = false;
};
// all bookkeeping here
template<typename U, U D>
struct details<U,D,std::enable_if_t<std::is_unsigned<U>::value && (D>0) > >{
static constexpr bool value = true;
static constexpr U dim = D; // Replaces BASE_DIM
static constexpr U units = T_bit_size<U>::value; // Replaces DIM
static constexpr bool divisible = (dim%units == 0);
typedef U type;
static constexpr U N_idx = divisible ? (dim/units) : (dim/units + 1); // Replaces N_DIM_IDX
static constexpr U L_idx = N_idx - 1; // Replaces POS_LAST_IDX
static constexpr U L_idx_N_pos = divisible ? (units) : (dim%units); // New!!!
static constexpr U L_idx_L_pos = L_idx_N_pos - 1; // Replaces POS_LAST
};
// one of type U
template<typename U>
struct unsigned_value_of{
static constexpr U one = 1;
};
В качестве примера в коде я бы его заменил:
// currently:
class something{
// stuff
/*1)*/ for(myuint k=0; k<=(POS_LAST_IDX); k++)
// stuff
/*2)*/ (stuff)&(1ULL << POS_LAST_IDX)
// stuff
};
// if replaced:
template<typename U, U D > /* some enable_if for only unsigned enabled*/
class something{
// stuff
/*1)*/ for(U k=0; k<details<U>::N_idx; k++)
// stuff
/*2)*/ (stuff)&(unsigned_value_of<U>::one << details<U>::L_idx_L_pos)
// stuff
};
Если я это сделаю, то это вероятно, двухдневная работа по тщательному выполнению замен и проверке, что я ничего не тормозил. Если я действительно заменю это, у меня есть общий код. Если произойдет какая-либо дальнейшая бухгалтерия, я могу добавить еще одного участника в details
.
Хорошо, поэтому мой главный вопрос - как это повлияет на производительность? Стоит ли ожидать значительных накладных расходов? Стоит ли ожидать каких-либо накладных расходов? Из-за этого оптимизация компилятора будет молчать?
Любые комментарии приветствуются.