【发布时间】:2011-01-03 15:03:51
【问题描述】:
在我编写的一个程序中,20% 的时间都花在了在内循环中找出 3 个数字中的最小值,在这个例程中:
static inline unsigned int
min(unsigned int a, unsigned int b, unsigned int c)
{
unsigned int m = a;
if (m > b) m = b;
if (m > c) m = c;
return m;
}
有什么方法可以加快速度吗?我也可以使用 x86/x86_64 的汇编代码。
编辑:回复一些 cmets:
* 使用的编译器是 gcc 4.3.3
* 就组装而言,我只是那里的初学者。我在这里要求组装,以学习如何做到这一点。 :)
* 我运行的是四核 Intel 64,因此支持 MMX/SSE 等。
* 在这里发布循环很困难,但我可以告诉你这是对 levenshtein 算法的高度优化的实现。
这是编译器为 min 的非内联版本提供的内容:
.globl min
.type min, @function
min:
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %edx
movl 12(%ebp), %eax
movl 16(%ebp), %ecx
cmpl %edx, %eax
jbe .L2
movl %edx, %eax
.L2:
cmpl %ecx, %eax
jbe .L3
movl %ecx, %eax
.L3:
popl %ebp
ret
.size min, .-min
.ident "GCC: (Ubuntu 4.3.3-5ubuntu4) 4.3.3"
.section .note.GNU-stack,"",@progbits
内联版本在 -O2 优化代码中(甚至我的标记 mrk = 0xfefefefe,在调用 min() 之前和之后)都被 gcc 优化掉了,所以我无法掌握它。
更新:我测试了 Nils 建议的更改,ehemient,但是使用 min() 的汇编版本没有明显的性能提升。但是,通过使用 -march=i686 编译程序,我得到了 12.5% 的提升,我猜这是因为整个程序正在受益于 gcc 使用此选项生成的新的更快指令。谢谢你们的帮助。
附: - 我使用 ruby 分析器来测量性能(我的 C 程序是一个由 ruby 程序加载的共享库),所以我只能花时间在 ruby 程序调用的顶级 C 函数上,最终调用 min( ) 在堆栈中。请看这个question。
【问题讨论】:
-
查看为该例程生成的程序集,看看是否能找到优化它的方法。
-
你能发布你的编译器生成的程序集吗?没有看到这一点,很难知道是否有可能走得更快。
-
另外,这是如何使用的?一些优化,例如向量运算,只能在某些情况下应用。我们可以期待什么级别的 CPU 支持? (SSE3?4.1?)
-
你能发布发生这种情况的循环吗?可能可以在循环的上下文中进行优化。
-
如果这是程序的 20%,程序有多么微不足道?对我来说听起来像是家庭作业问题。
标签: c performance assembly x86