C++ C++;使用开关展开循环的模板?
我的问题与类似,但我想混合编译时和运行时。具体来说,我在编译时知道一个常量C++ C++;使用开关展开循环的模板?,c++,templates,c++11,switch-statement,template-meta-programming,C++,Templates,C++11,Switch Statement,Template Meta Programming,我的问题与类似,但我想混合编译时和运行时。具体来说,我在编译时知道一个常量NBLOCK,我想在变量start\u块上写一个开关,该变量只有在运行时才知道,其中NBLOCK是开关中的条目数。以下是我使用宏得到的结果: #define CASE_UNROLL(i_loop) \ case i_loop : \ dst.blocks[i_loop+1] -= (load_unaligned_epi8(srcblock) != zero) & block1; \
NBLOCK
,我想在变量start\u块
上写一个开关,该变量只有在运行时才知道,其中NBLOCK
是开关中的条目数。以下是我使用宏得到的结果:
#define CASE_UNROLL(i_loop) \
case i_loop : \
dst.blocks[i_loop+1] -= (load_unaligned_epi8(srcblock) != zero) & block1; \
srcblock += sizeof(*srcblock);
switch(start_block)
{
CASE_UNROLL(0);
#if NBLOCKS > 2
CASE_UNROLL(1);
#endif
#if NBLOCKS > 3
CASE_UNROLL(2);
#endif
#if NBLOCKS > 4
CASE_UNROLL(3);
#endif
...
...
#if NBLOCKS > 15
CASE_UNROLL(14);
#endif
#if NBLOCKS > 16
#error "Too many blocks"
#endif
}
我觉得很难看。特别是如果我想把边界从16提高到32
我想知道是否有可能使用一些模板元编程来编写。困难的部分是,出于性能原因,使用跳转表而不是嵌套条件的序列来编译开关是至关重要的
请注意,问题非常类似于,但据我所知,这里提出的解决方案是通过使用混合编译/tun时间初始化函数指针数组来移除开关。我不能付钱给王子在这里调用函数
如果需要一些讨厌的扩展,我将与GCC合作 您只需将Boost.Preprocessor与
Boost\u PP\u REPEAT(计数、宏、数据)
一起使用即可:
这应扩大到:
switch(start_block)
{
CASE_UNROLL(0);
CASE_UNROLL(1);
CASE_UNROLL(2);
// ...
CASE_UNROLL(NBLOCK-1);
}
基于模板的展开:
template<int N>
struct loopUnroller
{
template<typename Operation>
inline void operator(Operation& op) { op(); loopUnroller<N-1>(op); }
};
template<>
struct loopUnroller<0>
{
template<typename Operation>
inline void operator(Operation& op) { op(); }
};
具有对数复杂性:
template<int N>
struct loopUnroller
{
template<typename Operation>
inline void operator(Operation& op) {
loopUnroller<N/2>(op);
loopUnroller<N/2>(op);
if (N%1) { op(); } // Will be optimized out if N is even.
}
};
template<int L>
struct loopUnroller
{
template<typename Operation>
inline void operator(Operation& op, int i) {
if (i & (1<<L)) {
for(int j = 0; j != 1<<L; ++j)
{
op();
}
}
loopUnroller<L-1>(op, i);
}
};
模板
结构循环展开器
{
模板
内联无效运算符(操作和操作){
活套展开器(op);
活套展开器(op);
if(N%1){op();}//将在N为偶数时进行优化。
}
};
具有动态复杂性:
template<int N>
struct loopUnroller
{
template<typename Operation>
inline void operator(Operation& op) {
loopUnroller<N/2>(op);
loopUnroller<N/2>(op);
if (N%1) { op(); } // Will be optimized out if N is even.
}
};
template<int L>
struct loopUnroller
{
template<typename Operation>
inline void operator(Operation& op, int i) {
if (i & (1<<L)) {
for(int j = 0; j != 1<<L; ++j)
{
op();
}
}
loopUnroller<L-1>(op, i);
}
};
模板
结构循环展开器
{
模板
内联无效运算符(操作和op,int i){
如果(i&(1不可能重复。它不是重复。在我的情况下,起点在运行时已知,终点在编译时已知。GCC能够展开代码,但它使用了大量跳转。此版本速度更快,因为只有一个跳转。但是它使用宏。我宁愿编写模板。我问为什么?它真的比编译代码?是的,快了30%。这里的开关在我的内部计算循环中。谢谢你的提示。它仍然不能回答模板是否可行的问题。我认为这不是,但我希望得到专家的答案。重点是,我想确保有一个开关,因为我只知道在运行时到起始点@hivert:这又是一个XY问题。您正在假设一个特定的解决方案。最后一段代码也将int i
作为运行时的起点,只是没有开关。