新的CPU指令集被编译系统应用要多久 - 弦外之音

/ 0评 / 0

我的环境是 ubuntu18,glibc 2.7,下面是我的代码:

#include <stdio.h>
#include <string.h>
int main() {
    char str[20] = "aacdf";
    int str_num = strlen(str);
    printf("str num is %d \n",str_num);
    return 0;
}

编译之后,直接 gdb 调试,查看汇编代码,发现 strlen() 的 函数的实现主要使用了 3 个汇编指令完成。

1,pcmpeqb,求掩码,上面是5个字符,求掩码之后就变成 0 0 0 0 -1 -1 -1 这种数据。

2,pmovmskb,转移掩码。

3,bsf,这个是位扫码指令,直接扫掩码,扫到 1 停止。

这些 是 SSE2 的指令集,实际上在 SSE4.1 提供了一个 pcmpistr 指令,可以完成上面 3 个指令干的活。


下面来看一下 glibc 库 2.7 版本strlen() 函数的代码实现,文件是 string/strlen.c 如下:

从代码可以看到,使用的是 C语言,里面没有嵌入汇编代码,所以这些 C程序 被编译成 什么样的 汇编指令,取决于编译系统,也就是 gcc,我的 gcc 版本是7.5,但很明显,编译系统是有点滞后的,SSE4.1 的 pcmpistr 指令2007年已经出了,但是直到 2018 年,gcc 7.5 编译 strlen 函数的时候还是没能用上 pcmpistr 指令。相差10多年,这个时间差就给了很多做性能优化的公司很多机会。


再看另一个例子。代码如下:

int main() {
    double a = 4.0;
    double b = 20.0;
    double c = 40.0;
    double d = (a * b) + c;
    return d;
}

这个例子编译出来的汇编指令,也没用 FMA 指令。

实际上如果编译系统比较厉害,是可以编译出这种代码,如下:

__asm__("movsd  -0x20(%rbp),%xmm0");
__asm__("movsd  -0x18(%rbp),%xmm1");
__asm__("movsd  -0x10(%rbp),%xmm2");
__asm__("vfmadd213sd %xmm2,%xmm1,%xmm0");

相关阅读:

1,《glibc官网》


由于笔者的水平有限, 加之编写的同时还要参与开发工作,文中难免会出现一些错误或者不准确的地方,恳请读者批评指正。如果读者有任何宝贵意见,可以加我微信 Loken1,QQ:2338195090。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注