Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C函数代码长度与处理器缓存_C_Function_Caching - Fatal编程技术网

C函数代码长度与处理器缓存

C函数代码长度与处理器缓存,c,function,caching,C,Function,Caching,由于C是面向过程的语言,在使用C时,我总是使用顺序代码,自上而下作为一个或几个C函数运行 有时,我会编写1000行的函数。因为我认为函数调用有开销。虽然这不会复制代码,但我可以说在长函数中复制的代码少于5% 那么,长函数对处理器缓存有什么影响呢?长函数会阻止更好的CPU缓存使用吗?CPU缓存是否像缓存整个C函数一样工作?如果处理器缓存不喜欢长函数,那么调用函数会更有效吗?一般来说,可读性应该放在第一位,并且您可以将其视为“最后的”优化,不会为您带来显著的性能提升 今天的CPU正在缓存指令和数据。

由于C是面向过程的语言,在使用C时,我总是使用顺序代码,自上而下作为一个或几个C函数运行

有时,我会编写1000行的函数。因为我认为函数调用有开销。虽然这不会复制代码,但我可以说在长函数中复制的代码少于5%


那么,长函数对处理器缓存有什么影响呢?长函数会阻止更好的CPU缓存使用吗?CPU缓存是否像缓存整个C函数一样工作?如果处理器缓存不喜欢长函数,那么调用函数会更有效吗?

一般来说,可读性应该放在第一位,并且您可以将其视为“最后的”优化,不会为您带来显著的性能提升

今天的CPU正在缓存指令和数据。一般来说,您应该优化数据布局和内存访问模式,但指令的排列方式也会影响指令缓存的利用率

调用非内联函数实际上是一种无条件跳转,很像
jmp
指令。此跳转使CPU开始从内存中的另一个(可能很远)位置获取指令。如果在指令缓存中找不到这个新位置,CPU将暂停,直到相应的内存被带到那里。理论上,如果代码不包含跳转和分支,CPU可以尽可能主动地预取指令

而且,你永远不知道“太远”到底有多远。向前或向后跳转几千字节很可能会导致缓存命中,因为目前常用的指令缓存大约是32KB

这是一个非常棘手的优化,我建议您首先查看数据布局和内存访问模式


另一个问题是在堆栈或寄存器中传递参数的开销。对于今天的CPU来说,这不是什么问题,因为整个堆栈在数据缓存中通常是“热”的,寄存器重命名甚至可以消除寄存器到寄存器移动到no-op的情况。

是的,函数调用有一些开销。然而,在过去25年左右的时间里,这一开销非常小,几乎无法衡量。长函数对缓存的影响可能只有在循环中包含大量代码时才会明显。我的小费?可读性FTW!当我说“其他人”的时候,我的意思是几个月后你也要写一些其他人容易阅读和理解的代码。但是函数会影响处理器缓存吗?如果长函数不适合处理器缓存,那么短函数调用是否比CPU缓存好?长函数调用1000行是正常的?是的,正确,我最终在循环中有很多代码,比如在循环中有100行。我不会说有这么长的函数是不寻常的,但由于可读性(还有可维护性!)大多数人避免编写如此长的函数的原因。经验法则:如果它能放入“页面”在您的编辑器中,它足够长了。谢谢您的回复。好的,那么条件跳转(例如,if,for,while循环)呢?一旦达到条件跳转,CPU会停止预取指令吗?这就是分支预测试图解决的问题。分支预测器会告诉CPU的其余部分最有可能的结果,并且它可以开始获取指令。它甚至可以推测性地执行一定数量的指令,在分支条件已知时反转它们的效果。好的,如果我使用长函数,那么堆栈中就会有很多局部变量。如果我使用很多函数,那么我将不得不将变量作为参数传递给函数,或者我将使用包含所有这些所需变量的结构对象,并在函数之间传递此结构指针。哪一个更好?far在指令缓存术语中的含义是什么?指令缓存可以处理排序函数(非内联)例如,进行递归调用而不进行内存访问,因为所有内容都在缓存中。此外,far在这里没有任何意义,因为cpu可以将指令缓存在很远的地方。它不需要缓存中间的代码。@Luiscolardo:的确,指令缓存可以容纳相距很远的指令块,并且所有内容都可以被缓存只要所有的块都适合缓存,就可以了,但许多远跳转(无论我们以何种方式定义“远”)的累积效应是,它会降低缓存的整体效率。简单地说,这意味着一旦缓存满了,另一个远跳转最终将需要从缓存中逐出其他东西。