我有一个i5-4250U,它有AVX2和FMA3.我正在测试Linux上的GCC 4.8.1中的一些密集矩阵乘法代码.下面是我编译的三种不同方式的列表.
SSE2: gcc matrix.cpp -o matrix_gcc -O3 -msse2 -fopenmp
AVX: gcc matrix.cpp -o matrix_gcc -O3 -mavx -fopenmp
AVX2+FMA: gcc matrix.cpp -o matrix_gcc -O3 -march=native -fopenmp -ffast-math
Run Code Online (Sandbox Code Playgroud)
SSE2和AVX版本的性能明显不同.但是,AVX2 + FMA并不比AVX版本好.我不明白这一点.假设没有FMA,我获得了超过80%的CPU峰值触发器,但我认为我应该能够用FMA做得更好.矩阵乘法应直接受益于FMA.我基本上是在AVX中同时做八个点产品.当我检查march=native它给出:
cc -march=native -E -v - </dev/null 2>&1 | grep cc1 | grep fma
...-march=core-avx2 -mavx -mavx2 -mfma -mno-fma4 -msse4.2 -msse4.1 ...
Run Code Online (Sandbox Code Playgroud)
所以我可以看到它已启用(只是为了确保我添加-mfma但它没有区别). ffast-math应该允许宽松的浮点模型如何在SSE/AVX中使用融合乘法 - 加法(FMA)指令
编辑:
基于Mysticial的评论我继续使用_mm256_fmadd_ps,现在AVX2 + FMA版本更快. 我不确定为什么编译器不会为我这样做. 对于超过1000x1000的矩阵,我现在得到大约80 GFLOPS(没有FMA的110%的峰值触发器).如果有人不信任我的峰值翻牌计算,这就是我所做的.
peak flops (no FMA) = frequency * simd_width * ILP * cores …Run Code Online (Sandbox Code Playgroud) 有没有快速/简单的方法来做到这一点(至少粗略估计)?
我是基准测试算法,我认为知道我的计算机执行指令的绝对速度并将其与我的渐近分析进行比较会很酷.
我正在寻找一种更快,更棘手的方法来将C中的两个4x4矩阵相乘.我目前的研究主要集中在具有SIMD扩展的x86-64汇编上.到目前为止,我已经创建了一个函数,比一个简单的C实现快6倍,这超出了我对性能改进的期望.不幸的是,只有在没有使用优化标志进行编译时(GCC 4.7),这种情况才会成立.随着-O2,C变得更快,我的努力变得毫无意义.
我知道现代编译器利用复杂的优化技术来实现几乎完美的代码,通常比巧妙的手工装配更快.但在少数性能关键的情况下,人类可能会尝试使用编译器争取时钟周期.特别是,当一些支持现代ISA的数学可以被探索时(就像我的情况一样).
我的函数如下(AT&T语法,GNU汇编程序):
.text
.globl matrixMultiplyASM
.type matrixMultiplyASM, @function
matrixMultiplyASM:
movaps (%rdi), %xmm0 # fetch the first matrix (use four registers)
movaps 16(%rdi), %xmm1
movaps 32(%rdi), %xmm2
movaps 48(%rdi), %xmm3
xorq %rcx, %rcx # reset (forward) loop iterator
.ROW:
movss (%rsi), %xmm4 # Compute four values (one row) in parallel:
shufps $0x0, %xmm4, %xmm4 # 4x 4FP mul's, 3x 4FP add's 6x mov's per row,
mulps %xmm0, %xmm4 # expressed in four sequences of 5 instructions,
movaps …Run Code Online (Sandbox Code Playgroud) 我用AVX一次计算八个点产品.在我目前的代码中,我做了类似的事情(在展开之前):
常春藤桥/桑迪桥
__m256 areg0 = _mm256_set1_ps(a[m]);
for(int i=0; i<n; i++) {
__m256 breg0 = _mm256_load_ps(&b[8*i]);
tmp0 = _mm256_add_ps(_mm256_mul_ps(arge0,breg0), tmp0);
}
Run Code Online (Sandbox Code Playgroud)
Haswell的
__m256 areg0 = _mm256_set1_ps(a[m]);
for(int i=0; i<n; i++) {
__m256 breg0 = _mm256_load_ps(&b[8*i]);
tmp0 = _mm256_fmadd_ps(arge0, breg0, tmp0);
}
Run Code Online (Sandbox Code Playgroud)
我需要多少次为每个案例展开循环以确保最大吞吐量?
对于使用FMA3的Haswell,我认为答案是每个循环的FLOPS用于沙桥和haswell SSE2/AVX/AVX2.我需要将循环展开10次.
对于Ivy Bridge,我认为它是8.这是我的逻辑.AVX添加的延迟为3,延迟乘以5.Ivy Bridge可以使用不同的端口同时进行一次AVX乘法和一次AVX添加.使用符号m进行乘法,a表示加法,x表示无操作,以及表示部分和的数字(例如m5表示乘以第5部分和)我可以写:
port0: m1 m2 m3 m4 m5 m6 m7 m8 m1 m2 m3 m4 m5 ...
port1: x x x x x a1 a2 a3 a4 a5 a6 a7 a8 ...
Run Code Online (Sandbox Code Playgroud)
因此,通过在9个时钟周期后使用8个部分和(4个来自负载,5个来自乘法),我可以在每个时钟周期提交一个AVX负载,一个AVX加法和一个AVX乘法.
我想这意味着在Ivy …
我刚读过这个问题:这段代码会损坏我的处理器吗?这让我想到了.
是否有可能仅通过软件损坏硬件?我听说"在过去的好时光"(TM)中,当硬盘驱动器由软件控制时,它们可能会碰到中心主轴,这会永久地损坏驱动器.
还有臭名昭着的切尔诺贝利病毒刚刚杀死BIOS并使机器无用,直到有人重新扫描它.
并且有微码更新,可以闪存到CPU(我不太了解它们).
但今天这还有可能吗?你能用软件破坏硬件吗?执行hcf(Halt&Catch fire)指令?通过增加WLAN输出功率烧烤猫?
我和编程领域的几个人进行了友好的竞争,最近我们对编写高效代码非常感兴趣.我们的挑战是尝试不惜任何代价(可读性,可重用性等)优化代码(在cpu时间和复杂性方面).
问题是,现在我们需要比较我们的代码,看看哪种方法比其他方法更好,但我们不知道任何工具用于此目的.
我的问题是,是否有一些(任何!)工具将一段代码作为输入并计算运行它所需的触发器或CPU指令的数量?有没有工具可以衡量代码的最佳性?
PS目标语言是c ++,但很高兴知道这些工具是否也存在于java中.
将__int64值转换__m64为与SSE一起使用的值的正确方法是什么?
我一直在寻找相当长一段时间,似乎无法找到一个官方/结论性的数字引用英特尔至强四核可以完成的单精度浮点运算/时钟周期的数量.我有一个Intel Xeon quadcore E5530 CPU.
我希望用它来计算我的CPU可以达到的最大理论FLOP/s.
MAX FLOPS =(#内核数)*(时钟频率(周期/秒))*(#FLOPS /周期)
任何指向我正确方向的东西都会有用.我已经发现每个循环的这个 FLOPS用于沙桥和haswell SSE2/AVX/AVX2
英特尔酷睿2和Nehalem:
4 DP FLOP /周期:2宽SSE2加+ 2宽SSE2乘法
8 SP FLOP /周期:4宽SSE加法+ 4宽SSE乘法
但我不确定这些数据在哪里被发现.他们是假设融合乘法加法(FMAD)操作吗?
编辑:使用它,在DP中我计算出英特尔引用的正确DP算术吞吐量为38.4 GFLOP/s(此处引用).对于SP,我得到双倍,76.8 GFLOP/s.我很确定4 DP FLOP /周期和8 SP FLOP /周期是正确的,我只想确认他们如何获得4和8的FLOP /周期值.
x86-64的SSE指令(向量指令)在哪里优于正常指令.因为我所看到的是,执行SSE指令所需的频繁加载和存储会使由于向量计算而产生的任何增益无效.那么有人可以给我一个示例SSE代码,它比普通代码表现更好.
也许是因为我分别传递了每个参数,就像这样......
__m128i a = _mm_set_epi32(pa[0], pa[1], pa[2], pa[3]);
__m128i b = _mm_set_epi32(pb[0], pb[1], pb[2], pb[3]);
__m128i res = _mm_add_epi32(a, b);
for( i = 0; i < 4; i++ )
po[i] = res.m128i_i32[i];
Run Code Online (Sandbox Code Playgroud)
有没有办法我可以一次性传递所有4个整数,我的意思是一次性传递整个128个字节pa?并分配res.m128i_i32给po一气呵成?