如何在现代x86-64 Intel CPU上实现每个周期4个浮点运算(双精度)的理论峰值性能?
据我所知,SSE 需要三个周期,add
而mul
大多数现代Intel CPU需要五个周期才能完成(参见例如Agner Fog的"指令表").由于流水线操作,add
如果算法具有至少三个独立的求和,则每个周期可以获得一个吞吐量.因为打包addpd
和标量addsd
版本都是如此,并且SSE寄存器可以包含两个,double
每个周期的吞吐量可以高达两个触发器.
此外,似乎(虽然我没有看到任何适当的文档)add
并且mul
可以并行执行,给出每个周期四个触发器的理论最大吞吐量.
但是,我无法使用简单的C/C++程序复制该性能.我最好的尝试导致大约2.7个翻牌/周期.如果有人可以贡献一个简单的C/C++或汇编程序,它可以表现出非常高兴的峰值性能.
我的尝试:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <sys/time.h>
double stoptime(void) {
struct timeval t;
gettimeofday(&t,NULL);
return (double) t.tv_sec + t.tv_usec/1000000.0;
}
double addmul(double add, double mul, int ops){
// Need to initialise differently otherwise compiler might optimise away
double sum1=0.1, sum2=-0.1, sum3=0.2, sum4=-0.2, sum5=0.0;
double mul1=1.0, mul2= 1.1, mul3=1.2, mul4= 1.3, …
Run Code Online (Sandbox Code Playgroud) 好吧,这只是一个有趣的练习,但是对于一些较旧的Linux系统来说编译程序不是太难,或者可以吗?
我可以访问几个运行linux的古老系统,也许看看它们在负载下的表现会很有趣.举个例子,我们想用Eigen做一些线性代数,这是一个很好的只有头的库.有没有机会在目标系统上编译它?
user@ancient:~ $ uname -a
Linux local 2.2.16 #5 Sat Jul 8 20:36:25 MEST 2000 i586 unknown
user@ancient:~ $ gcc --version
egcs-2.91.66
Run Code Online (Sandbox Code Playgroud)
也许不是......所以让我们在当前系统上编译它.以下是我的尝试,主要是失败的.更多的想法非常受欢迎.
编译 -m32 -march=i386
user@ancient:~ $ ./a.out
BUG IN DYNAMIC LINKER ld.so: dynamic-link.h: 53: elf_get_dynamic_info: Assertion `! "bad dynamic tag"' failed!
Run Code Online (Sandbox Code Playgroud)编译-m32 -march=i386 -static
:运行在所有相当新的内核版本上,但如果它们稍微更旧并且具有众所周知的错误消息则会失败
user@ancient:~ $ ./a.out
FATAL: kernel too old
Segmentation fault
Run Code Online (Sandbox Code Playgroud)
这是一个glibc
错误,它支持最小内核版本,例如我的系统上的内核2.6.4:
$ file a.out
a.out: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV),
statically linked, for GNU/Linux …
Run Code Online (Sandbox Code Playgroud)c++ ×2
architecture ×1
assembly ×1
c ×1
gcc ×1
glibc ×1
linux ×1
linux-kernel ×1
optimization ×1