高手请进,关于C与汇编效率的讨论

/*
有以下5种方法实现两个整数的交换

swap,swap0, swap1用汇编语言编写
swap2, swap3用C语言编写

swap用中间变量方式实现

swap0用xchg指令实现

swap1用xor方法实现

swap2也是用xor方法实现

swap3用中间变量方法实现

问题:目的是测一测不同的swap函数的执行效率,看看C和汇编、不同算法之间的差别,分别计了一下时间,本以为使用xchg指令时间应该最短,但是结果却是xchg时间最长,而用c语言写的程序时间却最短。查看反汇编,C语言写的swap函数指令并不比汇编swap指令少,执行上用时却最少,很让人费解。

更费解的是,调整一下函数的声明顺序,执行时间上也不尽相同。
请高手给一个合理解释,最好有对应的测试代码,证明这个情况到底源于哪里呢??

*/
#include "stdafx.h"
#include "stdio.h"
#include "stdlib.h"
#include "time.h"

void swap(int *x, int *y)
{
_asm
{
mov ecx, x
mov edx, y
mov eax, [ecx]
mov ebx, [edx]
mov [ecx], ebx
mov [edx], eax
}
}

void swap0(int *x, int *y)
{

_asm
{
mov ecx, x
mov edx, y
mov eax, [ecx]
xchg eax, [edx]
xchg eax, [ecx]
}

}

void swap1(int *x, int *y)
{
_asm
{
mov ecx, x
mov edx, y
mov eax, [ecx]
xor eax, [edx]
mov ebx, eax
xor ebx, [edx]
mov [edx], ebx
xor eax, ebx
mov [ecx], eax
}
}

void swap2 (int *x, int *y)
{
*x = *x ^ *y;
*y = *x ^ *y;
*x = *x ^ *y;
}

void swap3 (int *x, int *y)
{
register z;
z = *x;
*x = *y;
*y = z;
}

int main(void)
{
int z1 = 3, z2 = 4;
int i;
int c = 50000000;
clock_t x;

x = clock();
for (i = 0; i < c; i++)
swap0(&z1, &z2);
printf("t0 = %d\t asm xchg\n", clock() - x);

x = clock();
for (i = 0; i < c; i++)
swap1(&z1, &z2);
printf("t1 = %d\t asm xor\n", clock() - x);

x = clock();
for (i = 0; i < c; i++)
swap2(&z1, &z2);
printf("t2 = %d\t c xor\n", clock() - x);

x = clock();
for (i = 0; i < c; i++)
swap3(&z1, &z2);
printf("t3 = %d\t c temp\n", clock() - x);

x = clock();
for (i = 0; i < c; i++)
swap(&z1, &z2);
printf("t = %d\t asm temp\n", clock() - x);

getchar();
return 0;
}

比较两次结果

这是完全相同的程序和配置多次运行的差异,再看下面这个

这是去掉了优化配置后的运行结果。


前两个的差异和不稳定性,是多线程系统下任务分配造成的。第三个,说明工程配置和编译环境的干扰非常大。


本身来说,现在的编程环境下,各种优化各种兼容,造成了C编译器编译的程序,汇编和C语言进行相同的操作没有本质差别(只有优化差别),无法通过这个方式进行汇编和C的效率比较。


如果要比较,那么安装一个纯UNIX吧(这个下面还可以获取微妙级时间片),通过纯汇编程序和纯C程序进行比较,才能看到差别。


总结:当前C编译器下,汇编和C代码运算几乎没有差异,而xchg,我认为是编译器没有相关优化造成的结果。

温馨提示:答案为网友推荐,仅供参考
第1个回答  2013-09-27
目的是测一测不同的swap函数的执行效率,看看C和汇编、不同算法之间的差别,分别计了一下时间,本以为使用xchg指令时间应该最短,但是结果却是xchg时间最长,
--------------------------------------------------
xchg 是一个原子操作指令,会锁住内存总线,因此,会极大的降低效率,使得cpu流水线之类无法产生效果。xchg这个指令,优点是原子操作,缺点是效率低,当然时间最长。详细参见intel指令手册。

而用c语言写的程序时间却最短。查看反汇编,C语言写的swap函数指令并不比汇编swap指令少,执行上用时却最少,很让人费解。
------------------------------------------------
你的汇编指令编写的swap程序,无论是用到xchg,还是普通的中间变量,都是一些中规中矩的汇编过程。编译器无法优化。因为你已经是汇编程序了。而C语言写的交换程序,编译器会进行优化,编译器的开发者极其精通底层硬件体系结构。利用了一些底层硬件,你不知道的特性,比如流水线,cache等功能,效率当然大大提高。你不知道而已。

更费解的是,调整一下函数的声明顺序,执行时间上也不尽相同。
-------------------------------------------------------
具体是哪个函数。追问

就是调整了一下函数声明的顺序,比如把swap3放在最开始,似乎是最先声明的函数,执行时间上会慢下来,不知何故。
另外,能否简要举例说明一下C是怎么被优化成适合硬件特性的,谢谢

追答

可能是缓存cache问题吧。

刚开始没有任何缓存,所以速度慢。

比如第一个函数,没有cache,执行它的时候,把包含它的程序从磁盘读到内存。但是显然,一次性读取的大小,并不只是第一个函数,比如一次读取4k,显然会把后面几个函数全部读入。

所以,第二个第三个在读取第一个的时候一起读入了。所以就快了。

你可以,写几个无聊的函数,放在这些函数前面。那么这些swap函数就是平等的了。

比如无聊的函数可以这样写

void swap_wuliao1(int *x, int *y)
{
_asm
{
mov ecx, x
mov edx, y
mov eax, [ecx]
mov ebx, [edx]
mov [ecx], ebx
mov [edx], eax
}
}

void swap_wuliao2 (int *x, int *y)
{
*x = *x ^ *y;
*y = *x ^ *y;
*x = *x ^ *y;
}

这2个函数和后面真的使用的函数式一样的,仅仅名称不一样。

把这2个函数放在最前面执行。作为warm up函数。

本回答被提问者采纳
第2个回答  2013-09-27
使用客户方
相似回答