为什么sizeof ...(T)这么慢?实现C ++ 14 make_index_sequence没有sizeof ...(T) [英] why sizeof...(T) so slow? implement C++14 make_index_sequence without sizeof...(T)

查看:730
本文介绍了为什么sizeof ...(T)这么慢?实现C ++ 14 make_index_sequence没有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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆