首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在标量矩阵加法中使用vaddss而不是addss有什么好处?

在标量矩阵加法中使用vaddss而不是addss有什么好处?
EN

Stack Overflow用户
提问于 2017-02-19 08:06:39
回答 1查看 1.6K关注 0票数 4

实现了标量矩阵加法内核。

代码语言:javascript
复制
#include <stdio.h>
#include <time.h>
//#include <x86intrin.h>

//loops and iterations:
#define N 128
#define M N
#define NUM_LOOP 1000000


float   __attribute__(( aligned(32))) A[N][M],
        __attribute__(( aligned(32))) B[N][M],
        __attribute__(( aligned(32))) C[N][M];

int main()
{
int w=0, i, j;
struct timespec tStart, tEnd;//used to record the processiing time
double tTotal , tBest=10000;//minimum of toltal time will asign to the best time
do{
    clock_gettime(CLOCK_MONOTONIC,&tStart);

    for( i=0;i<N;i++){
        for(j=0;j<M;j++){
            C[i][j]= A[i][j] + B[i][j];
        }
    }

    clock_gettime(CLOCK_MONOTONIC,&tEnd);
    tTotal = (tEnd.tv_sec - tStart.tv_sec);
    tTotal += (tEnd.tv_nsec - tStart.tv_nsec) / 1000000000.0;
    if(tTotal<tBest)
        tBest=tTotal;
    } while(w++ < NUM_LOOP);

printf(" The best time: %lf sec in %d repetition for %dX%d matrix\n",tBest,w, N, M);
return 0;
}

在本例中,我使用不同的编译器标志编译了程序,内环的程序集输出如下:

gcc -O2 msse4.2:128X128矩阵在406490次重复中的最佳时间: 0.000024秒

代码语言:javascript
复制
movss   xmm1, DWORD PTR A[rcx+rax]
addss   xmm1, DWORD PTR B[rcx+rax]
movss   DWORD PTR C[rcx+rax], xmm1

gcc -O2 -mavx:128X128矩阵在1000001次重复中的最佳时间: 0.000009秒

代码语言:javascript
复制
vmovss  xmm1, DWORD PTR A[rcx+rax]
vaddss  xmm1, xmm1, DWORD PTR B[rcx+rax]
vmovss  DWORD PTR C[rcx+rax], xmm1

AVX版gcc -O2 -mavx

代码语言:javascript
复制
__m256 vec256;
for(i=0;i<N;i++){   
    for(j=0;j<M;j+=8){
        vec256 = _mm256_add_ps( _mm256_load_ps(&A[i+1][j]) ,  _mm256_load_ps(&B[i+1][j]));
        _mm256_store_ps(&C[i+1][j], vec256);
            }
        }

SSE版本gcc -O2 -sse4.2::

代码语言:javascript
复制
__m128 vec128;
for(i=0;i<N;i++){   
    for(j=0;j<M;j+=4){
    vec128= _mm_add_ps( _mm_load_ps(&A[i][j]) ,  _mm_load_ps(&B[i][j]));
    _mm_store_ps(&C[i][j], vec128);
            }
        }

在标量程序中,-mavxmsse4.2上的加速比为2.7倍。我知道avx有效地改进了ISA,这可能是因为这些改进。但是当我为AVXSSE用本质实现程序时,加速比是3x的一个因素。问题是: AVX标量比SSE快2.7倍,当我将它向量化时,速度是3x (这个问题的矩阵大小是128×128)。在标量模式下使用AVX和SSE有意义吗?但是矢量化方法必须更好,因为我在AVX中处理了8个元素,而SSE中处理了4个元素。正如perf stat报告的那样,所有程序的缓存丢失率都不到4.5%。

使用gcc -O2linux mintskylake

更新:简单地说,标量-AVX比标量-SSE快2.7倍,而AVX-256只比SSE-128快3倍,而它是矢量化的。我想可能是因为流水线。在标量中,我有3个vec-ALU,它们在矢量化模式下可能无法使用。我可能会把苹果比作橘子,而不是把苹果比作苹果,这可能是我无法理解的原因。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-02-19 14:24:22

您所观察到的问题是解释here。在Skylake系统上,如果AVX寄存器的上半部分是脏的,那么在AVX寄存器的上半部分存在对非vex编码的SSE操作的虚假依赖。在您的例子中,似乎在您的glibc 2.23版本中存在一个bug。在我的Skylake系统的Ubuntu 16.10和glibc 2.24,我没有问题。您可以使用

代码语言:javascript
复制
__asm__ __volatile__ ( "vzeroupper" : : : ); 

清除AVX寄存器的上半部分。我不认为您可以使用诸如_mm256_zeroupper这样的内部代码来修复这个问题,因为GCC会说它是SSE代码,而不识别内部代码。选项-mvzeroupper也不能工作,因为GCC再次认为它是SSE代码,不会发出vzeroupper指令。

顺便说一下,it's Microsoft's fault that the hardware has this problem.

更新:

Other people are apparently encountering this problem on Skylake。在printfmemsetclock_gettime之后观察到了这一现象。

如果您的目标是比较128位操作和256位操作,可以考虑使用-mprefer-avx128 -mavx (这对AMD特别有用)。但是,您将比较AVX256与AVX128,而不是AVX256与SSE。AVX128和SSE都使用128位操作,但它们的实现是不同的。如果你用基准测试,你应该提到你用的是哪一个。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42324992

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档