Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.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
Optimization 一个循环应该被取消多少次?_Optimization_Assembly_Dependencies - Fatal编程技术网

Optimization 一个循环应该被取消多少次?

Optimization 一个循环应该被取消多少次?,optimization,assembly,dependencies,Optimization,Assembly,Dependencies,我正在学习循环展开,以避免依赖项导致的暂停。我在互联网和文献中找到了很多例子,但我没有找到关于用于获得优化代码的算法如何工作的解释(当然,如果有这样的算法的话)。特别是,我不知道如何确定循环应该展开多少次。可以预先计算吗?你在写编译器吗?否则,您真的不应该自己展开循环。您最有可能相信编译器会在适用的地方为您进行适当的循环展开。您正在编写编译器吗?否则,您真的不应该自己展开循环。在编译器认为合适的情况下,您最有可能相信它会为您进行适当的循环展开。经验法则是您展开循环,以便: 在“自然”边界4、8

我正在学习循环展开,以避免依赖项导致的暂停。我在互联网和文献中找到了很多例子,但我没有找到关于用于获得优化代码的算法如何工作的解释(当然,如果有这样的算法的话)。特别是,我不知道如何确定循环应该展开多少次。可以预先计算吗?

你在写编译器吗?否则,您真的不应该自己展开循环。您最有可能相信编译器会在适用的地方为您进行适当的循环展开。

您正在编写编译器吗?否则,您真的不应该自己展开循环。在编译器认为合适的情况下,您最有可能相信它会为您进行适当的循环展开。

经验法则是您展开循环,以便:

  • 在“自然”边界4、8、16、32上进行操作。。字节
  • 您不会引入过大的寄存器压力(即,您不会开始将寄存器变为内存)
  • 您不会一次又一次地重复完全相同的指令序列

基本上,只要你能投入更多的资源工作,你就可以展开,当你不再能够衡量任何绩效收益时,你就可以停止。

经验法则是,你可以放松,以便:

  • 在“自然”边界4、8、16、32上进行操作。。字节
  • 您不会引入过大的寄存器压力(即,您不会开始将寄存器变为内存)
  • 您不会一次又一次地重复完全相同的指令序列

基本上,只要你能投入更多的资源来工作,你就会展开工作,当你不再能够衡量任何绩效提升时,你就会停止工作。

我想补充我的回答,因为尽管托尔比约恩·吉勒布林的回答是好的,但在我看来,这并不完整

由于展开,有不同的改进:

算法改进-例如,您的指令集允许处理四个字节而不是一个字节。托比约恩回答得很好

减少循环开销当循环体较小时,循环开销(通常为增量+比较+跳转)会消耗大量时间

total cost = N * (loop body + loop overhead)
展开一次,你就可以

total cost = N/2 * (2 * loop body + loop overhead)  
           = N * loop body + N / 2 * loop overhead
如果循环开销与循环体相比很小,那么展开不会以增加代码大小为代价获得任何收益。示例:当循环体的开销是循环开销的10倍时,展开最多可以提高5%

更好的配对-在具有多个管道(或准配对,例如寄存器重命名和微码生成)的体系结构上,展开可以提供更好的配对机会。同样,只有当环体很小时,它们才值得注意,但公式不能像上面那样容易给出


展开并不是无害的-请记住,即使在“好”的情况下展开也会使循环的代码大小增加一倍。这可能会从缓存中清除其他代码或数据。在现代桌面架构中,代码大小问题非常严重,因此经验法则是全局优化代码大小,局部热点优化速度

我想补充我的回答,因为尽管托尔比约恩·吉勒布林的回答很好,但在我看来并不完整

由于展开,有不同的改进:

算法改进-例如,您的指令集允许处理四个字节而不是一个字节。托比约恩回答得很好

减少循环开销当循环体较小时,循环开销(通常为增量+比较+跳转)会消耗大量时间

total cost = N * (loop body + loop overhead)
展开一次,你就可以

total cost = N/2 * (2 * loop body + loop overhead)  
           = N * loop body + N / 2 * loop overhead
如果循环开销与循环体相比很小,那么展开不会以增加代码大小为代价获得任何收益。示例:当循环体的开销是循环开销的10倍时,展开最多可以提高5%

更好的配对-在具有多个管道(或准配对,例如寄存器重命名和微码生成)的体系结构上,展开可以提供更好的配对机会。同样,只有当环体很小时,它们才值得注意,但公式不能像上面那样容易给出


展开并不是无害的-请记住,即使在“好”的情况下展开也会使循环的代码大小增加一倍。这可能会从缓存中清除其他代码或数据。在现代桌面架构中,代码大小问题非常严重,因此经验法则是全局优化代码大小,局部热点优化速度

有时甚至可以不展开循环(对于Core2和up处理器),因为它们有一个“循环流检测器”(他们称之为LSD)。 只需在《英特尔优化指南》中查找即可


如果代码确实适合(非常小的)队列,那么处理器不需要从一级指令缓存中获取/解码指令,这可以提供一些性能。

有时甚至不展开循环(对于Core2和更高版本的处理器)是有意义的,因为它们有一个“循环流检测器”(它们称之为LSD)。 只需在《英特尔优化指南》中查找即可


如果代码确实适合(非常小的)队列,则处理器不需要从一级指令缓存中获取/解码指令,这样可以提供一定的性能。

严格来说不是这样-在某些情况下,手动循环展开可以产生比编译器更好的结果-但通常是这样,最好让编译器来做。对于一些较新的微体系结构,最好还是让硬件进行循环展开。我不是自己展开的。我正在为微控制器编写一些C代码,在检查编译器输出的机器代码时,我发现循环已经展开。我只是想知道它是怎么工作的。我不打算手工做这件事,严格说来也不是这样-