Assembly 什么';这是一个简单C函数的例子,它在内联汇编中实现得更快?

Assembly 什么';这是一个简单C函数的例子,它在内联汇编中实现得更快?,assembly,inline-assembly,Assembly,Inline Assembly,我很难用内联汇编打败我的编译器 什么是一个好的、非人工设计的函数示例,编译器很难做到真正、非常快速和简单?但使用内联汇编实现这一点相对简单。我战胜编译器的最佳方法是使用一个简单的memcpy例程。。。我跳过了很多基本的设置工作(例如,我不需要太多的堆栈帧,所以我在那里保存了一些循环),并且做了一些非常棘手的事情 那是大约6年前的事了,有一些质量未知的专有编译器。我将不得不挖掘我的代码,并尝试它对GCC现在;我不知道它会变得更快,但我不排除这种可能性 最后,尽管我的memcpy平均比我们的C库快1

我很难用内联汇编打败我的编译器


什么是一个好的、非人工设计的函数示例,编译器很难做到真正、非常快速和简单?但使用内联汇编实现这一点相对简单。

我战胜编译器的最佳方法是使用一个简单的memcpy例程。。。我跳过了很多基本的设置工作(例如,我不需要太多的堆栈帧,所以我在那里保存了一些循环),并且做了一些非常棘手的事情

那是大约6年前的事了,有一些质量未知的专有编译器。我将不得不挖掘我的代码,并尝试它对GCC现在;我不知道它会变得更快,但我不排除这种可能性


最后,尽管我的memcpy平均比我们的C库快15倍,但我还是把它放在了我的后口袋里,以备不时之需。它是我玩PPC汇编的玩具,在我们的应用程序中不需要速度提升。

如果你想做SIMD操作之类的事情,你可能会打败编译器。这将需要对体系结构和指令集有很好的了解。

< P>如果你不考虑SIMD操作欺骗,你通常可以编写比你的编译器自动向量化能力更好的SIMD程序集(如果它甚至有自动矢量化)< /P> 一个非常基本的SSE(x86的SIMD指令集之一)教程。用于Visual C++在线汇编。 编辑:如果您想自己尝试,这里有一对小函数。这是一个n长度点积的计算。一个是使用SSE2指令内联(GCC内联语法),另一个是非常基本的C

这非常简单,如果一个好的编译器不能向量化简单的C循环,我会非常惊讶,但是如果不能,你应该看到SSE2的速度有所提高。如果我使用更多寄存器,SSE2版本可能会更快,但我不想扩展我非常弱的SSE技能:)

float dot_asm(float*a,float*b,int n)
{
浮动ans=0;
int i;
//我没有检查大小为%8!=0的数组。
而(n>0){
浮动tmp[4]uuuu属性_uuu((对齐(16));
__asm\uuuuuuuuuuuuuuuuuu挥发性__(
xorps%%xmm0,%%xmm0\n\t
movups(%0),%%xmm1\n\t
movups 16(%0),%%xmm2\n\t
movups(%1),%%xmm3\n\t
movups 16(%1),%%xmm4\n\t
添加$32,%0\n\t
添加$32,%1\n\t
mulps%%xmm3,%%xmm1\n\t
mulps%%xmm4,%%xmm2\n\t
addps%%xmm2,%%xmm1\n\t
“addps%%xmm1,%%xmm0”
:“+r”(a),“+r”(b)
:
:“xmm0”、“xmm1”、“xmm2”、“xmm3”、“xmm4”);
__asm\uuuuuuuuuuuuuuuuuu挥发性__(
“movaps%%xmm0,%0”
:“=m”(tmp)
: 
:“xmm0”,“内存”);
对于(i=0;i<4;i++){
ans+=tmp[i];
}
n-=8;
}
返回ans;
}
浮点点c(浮点*a,浮点*b,整数n){
浮动ans=0;
int i;
对于(i=0;i
除非你是一名工程师,否则击败编译器的几率很低

上面链接中的一个片段

例如,面向位的“XOR” %EAX,%EAX”指令是 将寄存器设置为零的最快方法 在x86的早期几代中, 但大多数代码是由 编译器和编译器很少使用 生成的异或指令。那么IA呢 设计师们决定将 常见编译器 生成最前面的指令 组合译码逻辑的实现 使文字“MOVL$0,%EAX” 指令的执行速度比 异或指令


我使用通用的“C海峡”实现了简单的互相关。然后,当它花费的时间比我现有的时间片更长时,我求助于算法的显式并行化,并使用处理器的内在特性强制在计算中使用特定的指令。对于这种特殊情况,计算时间从>30ms减少到略多于4ms。在下一次数据采集之前,我有15毫秒的时间完成处理

这是VLWI处理器上的SIMD类型优化。这只需要4个左右的处理器内部函数,它们基本上是在源代码中给出函数调用外观的汇编语言指令。对于内联汇编也可以这样做,但对于处理器内部函数,语法和寄存器管理会更好一些


除此之外,若尺寸很重要,那个么汇编程序就是王者。我和一个家伙一起上学,他用不到512字节的时间编写了一个全屏文本编辑器。

我有一个校验和算法,它要求单词按一定的位数旋转。为了实现它,我有以下宏:

//rotate word n right by b bits
#define ROR16(n,b) (((n)>>(b))|(((n)<<(16-(b)))&0xFFFF))

//... and inside the inner loop: 
sum ^= ROR16(val, pos);
更有效的等效手工生成的装配是:

 mov       cl,dx
 ror       ax,cl
 xor       bx,ax
我还没有弄清楚如何从纯“c”代码发出
ror
指令。然而
在写这篇文章时,我想起了编译器的内部函数。我可以使用以下命令生成第二组指令:

sum ^= _rotr16(val,pos);

所以我的答案是:即使你认为你可以打败纯c编译器,在使用内联汇编之前检查一下内部函数。

因为它与iPhone和汇编代码相关,所以我将给出一个与iPhone世界相关的示例(而不是一些sse或x86 asm)。 如果有人决定为某个真实世界的应用程序编写汇编代码,那么很可能是某种数字信号处理或图像处理。示例:为voip应用程序转换RGB像素的颜色空间、将图像编码为jpeg/png格式或将声音编码为mp3、amr或g729。 在声音编码的情况下,有许多例程不能被编译器翻译成高效的asm代码,它们在C中根本没有等价物
 mov       cl,dx
 ror       ax,cl
 xor       bx,ax
sum ^= _rotr16(val,pos);
int saturated_add(int a, int b) { int result = a + b; if (((a ^ b) & 0x80000000) == 0) { if ((result ^ a) & 0x80000000) { result = (a < 0) ? 0x80000000 : 0x7fffffff; } } return result; } res1 = a + b1*c1; res2 = a + b2*c2; res3 = a + b3*c3;