在不支持 sse3 及其以后的 x86_64 向量指令的环境中运行 dpdk 程序的修改思路

在不支持 sse3 及其以后的 x86_64 向量指令的环境中运行 dpdk 程序的修改思路

问题描述

某 qemu 虚机环境使用 qemu 模拟的 cpu,不支持 SSSE3、SSE4 及之后的向量指令,运行 dpdk 程序后有如下报错信息:

ERROR: This system does not support "SSSE3".
Please check that RTE_MACHINE is set correctly.
EAL: FATAL: unsupported cpu type.

运行环境的 cpu 支持的 cpuflags 如下:

fpu de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pse36 clflush mmx fxsr sse sse2 syscall nx lm rep_good nopl xtopology cpuid tsc_known_freq pni cx16 x2apic hypervisor lahf_lm cpuid_fault pti

确认仅支持 sse、sse2 以及 pni(SSE3)向量指令,其余更高级的指令并不支持。这里需要值得一提的是 pni 标志,全称是 Prescott New Instructions,实际是 SSE3 指令集的别名。

备注:使用的 dpdk 版本为 19.11,虚拟机使用的网卡是 virtio 网卡,下文内容均基于此版本实现展开。

dpdk 中检测编译配置的 cpuflags 与运行时机器的 cpuflags 一致行的过程

dpdk 项目中 mk/rte.cpuflags.mk 负责生成 RTE_COMPILE_TIME_CPULAGS 宏的内容,并为 dpdk 源程序添加此宏定义。

一般在 dpdk 编译之前会使用脚本指定不同的编译类型生成不同的编译配置 .config 文件,.config 文件由 config 目录下保存的文件模版生成而来,其中保存了 RTE_MACHINE 的配置内容,部分列举如下:

config/defconfig_x86_64-native-linux-gcc:6:CONFIG_RTE_MACHINE="native"
config/defconfig_x86_64-native-bsdapp-clang:6:CONFIG_RTE_MACHINE="native"
config/defconfig_arm64-octeontx2-linux-gcc:7:CONFIG_RTE_MACHINE="octeontx2"
...........................................................................

CONFIG_RTE_MACHINE 内容在编译脚本中被使用,其值作为子目录名称,在 mk/machine/ 目录中配置 MACHINE_CFLAGS 变量以获取到 gcc -march 选项的值配置,指定 machine 的类型。native 类型的配置如下:

MACHINE_CFLAGS = -march=native

此后 dpdk mk/rte.cpuflags.mk 脚本调用 gcc -dM -E 并添加 MACHINE_CFLAGS 及其它相关变量来生成编译目标对依赖的不同 cpuflags 的支持情况并配置 CPUFLAGS 变量,配置示例如下:

AUTO_CPUFLAGS := $(shell $(CC) $(MACHINE_CFLAGS) $(WERROR_FLAGS) $(EXTRA_CFLAGS) -dM -E - < /dev/null)

# adding flags to CPUFLAGS

ifneq ($(filter $(AUTO_CPUFLAGS),__SSE__),)
CPUFLAGS += SSE
endif

ifneq ($(filter $(AUTO_CPUFLAGS),__SSE2__),)
CPUFLAGS += SSE2
endif
................................................

AUTO_CPUFLAGS 指定的命令行的运行示例如下:

[root@localhost mk]$ gcc -march=native -dM - -E < /dev/null | grep SSE
#define __SSE4_1__ 1
#define __SSE4_2__ 1
#define __SSE2_MATH__ 1
#define __SSE_MATH__ 1
#define __SSE2__ 1
#define __SSSE3__ 1
#define __SSE__ 1
#define __SSE3__ 1

能够看到 gcc 会生成目标机器支持的 cpuflags 的内部宏定义,dpdk 通过判断这些宏来设置 CPUFLAGS,最后用 CPUFLAGS 转化设置为 RTE_COMPILE_TIME_CPUFLAGS,其值示例如下:

RTE_CPUFLAG_SSE,RTE_CPUFLAG_SSE2,RTE_CPUFLAG_SSE3,RTE_CPUFLAG_SSSE3,RTE_CPUFLAG_SSE4_1,RTE_CPUFLAG_SSE4_2

同时 dpdk 会为每个 CPUFLAGS 设置 RTE_MACHINE_CPUFLAG_XXX 宏作为编译参数(XXX 为单个 CPUFLAG 的名称),供 dpdk 内部代码使用。

dpdk 内部 rte_cpu_is_supported 函数中引用了 RTE_COMPILE_TIME_CPUFLAGS 宏,保存了编译时的 cpuflags。rte_cpu_is_supported 函数在运行时会检测运行环境的 cpu 是否支持 RTE_COMPILE_TIME_CPUFLAGS 宏定义的每个依赖的 cpuflags,不支持则打印错误信息,dpdk 程序终止运行。

备注:gcc 官方手册中对 -march 指定 native 参数的解释:

-march=native

This selects the CPU to generate code for at compilation time by determining the processor type of the compiling machine. Using -march=native enables all instruction subsets supported by the local machine (hence the result might not run on different machines). Using -mtune=native produces code optimized for the local machine under the constraints of the selected instruction set.

dpdk 中对向量指令的使用情况是怎样的?

dpdk-19.11 对向量指令的使用情况 这篇文章中,我列举了 dpdk-19.11 对向量指令的使用情况,有了这个输入,就清楚了哪里会产生问题。

如何让 dpdk 程序去掉对 SSSE3、SSE4 等更高级指令的使用?

1. 从编译上识别依赖,修改 .config 文件关闭相关模块

在编译前指定 EXTRA_CFLAGS 变量值为 -march=nocona,从 gcc 官方手册中查到,此 machine 支持 MMX、SSE、SSE2、SSE3 与 FXSR 指令集与目标虚拟机支持的向量指令基本一致。

识别后关闭能够关闭的模块。

2. 对于必须使用的模块,单独修改 Makefile 文件配置单独的 -march 并分析如何避免使用向量指令

有两个主要示例:

  1. rte_memcpy.h 中 rte_memcpy 函数替换为标准的 memcpy 函数
  2. rte_hash 模块,修改代码中调用 hash_create 的逻辑,在 hash 创建后调用 rte_hash_set_cmp_func 函数将 cmp 函数设置为 memcpu 不使用向量指令实现

总结一下,修改思路如下:

  1. 识别依赖 ssse3、sse4 及更高级向量指令的内容,优先在编译时关闭
  2. 不能关闭的配置正常编译 ssse3、sse4 等向量指令,配置不使用向量指令的执行逻辑,如 hash 模块、acl 模块等
  • 11
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值