【发布时间】:2010-07-20 07:52:51
【问题描述】:
我有两种方法来编写相同的功能。
方法一:
doTheWork(int action)
{
for(int i = 0 i < 1000000000; ++i)
{
doAction(action);
}
}
方法二:
doTheWork(int action)
{
switch(action)
{
case 1:
for(int i = 0 i < 1000000000; ++i)
{
doAction<1>();
}
break;
case 2:
for(int i = 0 i < 1000000000; ++i)
{
doAction<2>();
}
break;
//-----------------------------------------------
//... (there are 1000000 cases here)
//-----------------------------------------------
case 1000000:
for(int i = 0 i < 1000000000; ++i)
{
doAction<1000000>();
}
break;
}
}
假设函数doAction(int action) 和函数template<int Action> doAction() 由大约10 行代码组成,这些代码将在编译时内联。调用doAction(#) 在功能上等同于doAction<#>(),但非模板化的doAction(int value) 比template<int Value> doAction() 慢一些,因为在编译时参数值已知的情况下,可以在代码中进行一些很好的优化。
所以我的问题是,在模板化函数的情况下,是所有数百万行代码都填充 CPU L1 缓存(以及更多)(从而大大降低性能),还是只填充 doAction<#>() 的行当前运行的循环是否被缓存?
【问题讨论】:
-
“让我们假设函数 doAction(int action) 和函数模板
doAction() 包含大约 10 行代码,这些代码将在编译时内联。”编译器通常不够聪明,无法优化您的模板版本,切换会比您的 L1 缓存更严重地降低您的性能 -
我明白你的意思是这么大的开关是那里性能的最大问题。但我最感兴趣的是缓存 L1 是否在第二种方法中被填满并且有点问题,或者根本没有问题。我只是不知道它是如何工作的。我还想知道为什么编译器不知道如何内联函数的模板版本,假设它非常相似但比常规函数简单一点?