Optimization 此代码是否填充CPU缓存?
我有两种方法来编程相同的功能 方法1:Optimization 此代码是否填充CPU缓存?,optimization,cpu-cache,Optimization,Cpu Cache,我有两种方法来编程相同的功能 方法1: doTheWork(int action) { for(int i = 0 i < 1000000000; ++i) { doAction(action); } } doTheWork(int操作) { 对于(int i=0 i
doTheWork(int action)
{
for(int i = 0 i < 1000000000; ++i)
{
doAction(action);
}
}
doTheWork(int操作)
{
对于(int i=0 i<100000000;++i)
{
行动;
}
}
方法2:
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;
}
}
doTheWork(int操作)
{
开关(动作)
{
案例1:
对于(int i=0 i<100000000;++i)
{
doAction();
}
打破
案例2:
对于(int i=0 i<100000000;++i)
{
doAction();
}
打破
//-----------------------------------------------
//…(这里有100万例)
//-----------------------------------------------
案例1000000:
对于(int i=0 i<100000000;++i)
{
doAction();
}
打破
}
}
让我们假设函数
doAction(int action)
和函数template doAction()
包含大约10行代码,这些代码将在编译时内联。调用doAction(#)
在功能上等同于doAction()
,但是非模板化的doAction(int值)
要比template doAction()
慢一些,因为在编译时参数值已知时,可以在代码中进行一些很好的优化
因此,我的问题是,在模板函数的情况下,是否所有数百万行代码都填满了CPU一级缓存(以及更多的缓存)(从而大大降低了性能),还是只有
doAction()的行
在当前正在运行的循环中是否缓存?一级指令缓存将只包含最近或预期近期执行的指令。因此,第二种方法不能仅仅因为代码就填充一级缓存。您的执行路径将导致它加载表示正在运行的当前循环的模板实例化版本。当您移动到下一个循环时,它通常会使最近使用最少(LRU)的缓存线无效,并将其替换为下一个执行的缓存线
换句话说,由于两种方法的循环性质,一级缓存在这两种情况下都会表现出色,不会成为瓶颈。这取决于实际的代码大小-10行代码可能很少或很多-当然取决于实际的机器 然而,方法2严重违反了这一几十年的经验法则:指令便宜,内存访问不便宜 可扩展性限制 您的优化通常是线性的-您可能会减少10、20甚至30%的执行时间。达到缓存限制是高度非线性的,就像“撞到砖墙”中的非线性一样 一旦您的代码大小显著超过二级/三级缓存的大小,方法2就会损失大量时间,高端消费系统的以下估计结果表明:
- 具有
峰值内存带宽的DDR3-133310667MB/s
- 具有~
75000 MIPS的英特尔酷睿i7极限
我发现以下数字(不同来源,因此很难比较): i7 Nehalem二级缓存(256K,>200GB/s带宽),几乎可以满足x86指令的要求,但可能无法满足x64的要求 此外,只有在以下情况下,二级缓存才会完全启动
- 您对下一条指令有完美的预测,或者您没有第一次运行惩罚,并且它完全适合缓存
- 没有大量的数据被处理
- “内部循环”中没有其他重要代码
- 此核心上没有执行线程
考虑到这一点,您可能会更早地丢失,尤其是在缓存较小的CPU/板上。“让我们假设函数doAction(int action)和函数模板
doAction
实例化不再折叠,代码需要从L2/L3/主存中提取。使用典型的内存/执行周期比率,即使您完全预测下一步会出现什么指令,您也无法足够快地将它们放入一级缓存。