为什么sizeof ...(T)这么慢?实现C ++ 14 make_index_sequence没有sizeof ...(T) [英] why sizeof...(T) so slow? implement C++14 make_index_sequence without sizeof...(T)
问题描述
我发现C ++ 14的实现make_index_sequence'algorithm':
template< int ...> struct index_sequence {using type = index_sequence; };
template<类型名T>使用invoke = typename T :: type;
template<类型名称T,类型名称U> struct concate;
template< int ... i,int ... j>
struct concate< index_sequence< i ...>,index_sequence< j ...> >
:index_sequence< i ...,(j + sizeof ...(i))...> {};
// \ /
// ----------
//我觉得这里慢慢。
template< int n>
struct make_index_sequence_help:concate <
invoke < make_index_sequence_help< n / 2>>> ;,
调用< make_index_sequence_help< n-n / 2>
> {};
模板<> struct make_index_sequence_help< 0> :index_sequence<> {};
模板<> struct make_index_sequence_help< 1> :index_sequence< 0> {};
template< int n>使用make_index_sequence = invoke< make_index_sequence_help< n> > ;;
int main()
{
使用iseq = make_index_sequence< 1024> ; // successfull
using jseq = make_index_sequence< 1024 * 16> ; //很多编译时间!
using kseq = make_index_sequence< 1024 * 64> ; //无法编译:memory exhauted!
};
但是,当我替换sizeof ... i)到concate的具体数,然后make_index_sequence< 1024 * 64> - 编译速度非常快。
int s,类型名称T,类型名称U> struct concate;
template< int s,int ... i,int ... j>
struct concate< s,index_sequence< i ...>,index_sequence< j ...> >
:index_sequence< i ...,(j + s)...> {};
//和
template< int n>
struct make_index_sequence_help:concate<
n / 2,
调用< make_index_sequence_help< n / 2> >,
invoke< make_index_sequence_help< n-n / 2> >
> {};
问:为什么sizeof ...(i)这么慢? / p>
我用gcc测试4.8.1
更新:
对于第一种情况: 1024 * 16)。
g ++ -Wall -cctx_fptr.cpp-g -O2 -std = c ++ 11 -ftime-report
执行时间(秒)
垃圾回收:0.06(1%)usr 0.00(0%)sys 0.06(0%)wall 0 kB(0%)ggc
preprocessing :0.03(0%)usr 0.04(2%)系统0.09(1%)壁293kB(0%)ggc
解析器:10.41(97%)usr 1.61 2829842 kB(99%)ggc
名称查找:0.12(1%)usr 0.04(2%)sys 0.23(2%)wall 7236 kB(0%)ggc
dead store elim1:0.01 (%)usr 0.00(0%)sys 0.00(0%)wall 0 kB(0%)ggc
symout:0.15(1%)usr 0.00 %)ggc
未计入todo:0.00(0%)usr 0.01(1%)sys 0.00(0%)wall 0 kB(0%)ggc
TOTAL:10.78 1.70 12.55 2850835 kB
对于第二种情况:(所有1024,1024 * 16和1024 * 64)
g ++ -Wall -cctx_fptr.cpp-g -O2 -std = c ++ 11 -ftime-report
执行时间b $ b预处理:0.02(2%)usr 0.01(5%)系统0.05(4%)壁293 kB(0%)ggc
解析器:0.54(45% 50%)wall 95339 kB(58%)ggc
名称查找:0.47(39%)usr 0.04(21%)sys 0.47(33%)wall 20197 kB(12%)ggc
树PRE: 0.01(1%)usr 0.00(0%)系统0.00(0%)壁1 kB(0%)ggc
varconst:0.00(0%)usr 0.01 kB(0%)ggc
symout:0.17(14%)usr 0.03(16%)sys 0.18(13%)wall 47092 kB(29%)ggc
总计:1.21 0.19 1.41 163493 kB
编译速度慢,使用大量内存,因为递归扩展模板。这是在编译时完成的,它创建了大量的类型,这可以使用大量的内存。它不是由sizeof或任何其他单独的语句引起的。这是递归,导致模板扩展的每一个位都是昂贵的。
我碰到这个完全相同的问题与VC ++ - 我发现我的编译会得到任意慢,因为我把较大的常数传递给我写的模板函数。
当然,在我的情况下,我是 编译器运行缓慢。但是,这可能会有所帮助:https://randomascii.wordpress.com/2014/03/10/making-compiles-slow/
I found implement of C++14 make_index_sequence 'algorithm':
template< int ... > struct index_sequence{ using type = index_sequence; };
template< typename T> using invoke = typename T :: type ;
template< typename T, typename U > struct concate;
template< int ...i, int ... j>
struct concate< index_sequence<i...>, index_sequence<j...> >
: index_sequence< i... , (j + sizeof ... (i ) )... > {};
// \ /
// ----------
// I think here is slowly.
template< int n>
struct make_index_sequence_help : concate<
invoke< make_index_sequence_help<n/2>>,
invoke< make_index_sequence_help<n-n/2>>
> {};
template<> struct make_index_sequence_help <0> : index_sequence<>{};
template<> struct make_index_sequence_help <1> : index_sequence<0>{};
template< int n> using make_index_sequence = invoke< make_index_sequence_help<n> >;
int main()
{
using iseq = make_index_sequence< 1024 > ; // successfull
using jseq = make_index_sequence< 1024 * 16 > ; // a lot of compile time!!!
using kseq = make_index_sequence< 1024 * 64 > ; // can't compile: memory exhauted!!!
};
But, when I replace sizeof...(i) to concrete number from 'concate', then make_index_sequence< 1024 *64> -compiled very fast.
template< int s, typename T, typename U > struct concate;
template< int s, int ...i, int ...j >
struct concate< s, index_sequence<i...>, index_sequence<j...> >
: index_sequence< i..., ( j + s ) ... > {};
// and
template< int n >
struct make_index_sequence_help : concate<
n / 2 ,
invoke< make_index_sequence_help< n / 2 > >,
invoke< make_index_sequence_help< n - n/2 > >
>{};
Q: Why sizeof ... (i ) so slow ?
I test with gcc 4.8.1 Update:
For first case: ( only 1024 and 1024*16 ).
g++ -Wall -c "ctx_fptr.cpp" -g -O2 -std=c++11 -ftime-report
Execution times (seconds)
garbage collection : 0.06 ( 1%) usr 0.00 ( 0%) sys 0.06 ( 0%) wall 0 kB ( 0%) ggc
preprocessing : 0.03 ( 0%) usr 0.04 ( 2%) sys 0.09 ( 1%) wall 293 kB ( 0%) ggc
parser : 10.41 (97%) usr 1.61 (95%) sys 12.01 (96%) wall 2829842 kB (99%) ggc
name lookup : 0.12 ( 1%) usr 0.04 ( 2%) sys 0.23 ( 2%) wall 7236 kB ( 0%) ggc
dead store elim1 : 0.01 ( 0%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 0 kB ( 0%) ggc
symout : 0.15 ( 1%) usr 0.00 ( 0%) sys 0.15 ( 1%) wall 12891 kB ( 0%) ggc
unaccounted todo : 0.00 ( 0%) usr 0.01 ( 1%) sys 0.00 ( 0%) wall 0 kB ( 0%) ggc
TOTAL : 10.78 1.70 12.55 2850835 kB
For second case: ( all 1024, 1024*16 and 1024 * 64 )
g++ -Wall -c "ctx_fptr.cpp" -g -O2 -std=c++11 -ftime-report
Execution times (seconds)
preprocessing : 0.02 ( 2%) usr 0.01 ( 5%) sys 0.05 ( 4%) wall 293 kB ( 0%) ggc
parser : 0.54 (45%) usr 0.10 (53%) sys 0.71 (50%) wall 95339 kB (58%) ggc
name lookup : 0.47 (39%) usr 0.04 (21%) sys 0.47 (33%) wall 20197 kB (12%) ggc
tree PRE : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 1 kB ( 0%) ggc
varconst : 0.00 ( 0%) usr 0.01 ( 5%) sys 0.00 ( 0%) wall 17 kB ( 0%) ggc
symout : 0.17 (14%) usr 0.03 (16%) sys 0.18 (13%) wall 47092 kB (29%) ggc
TOTAL : 1.21 0.19 1.41 163493 kB
The compilation is slow and uses a lot of memory because you are recursively expanding templates. This is being done at compile time, it creates a large number of types, and this can use a lot of memory. It is not caused by sizeof or any other individual statement. It is the recursion that causes every bit of the template expansion to be expensive.
I've hit this exact same problem with VC++ -- I found that my compiles would get arbitrarily slow as I passed in larger constants to a template function that I wrote.
Of course, in my case I was trying to make the compiler run slowly. But still, maybe this will be helpful:
https://randomascii.wordpress.com/2014/03/10/making-compiles-slow/
这篇关于为什么sizeof ...(T)这么慢?实现C ++ 14 make_index_sequence没有sizeof ...(T)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!