相关疑难解决方法(0)

为什么mulss在Haswell上只用了3个周期,与Agner的指令表不同?

我是指令优化的新手.

我对一个简单的函数dotp进行了简单的分析,该函数用于获取两个浮点数组的点积.

C代码如下:

float dotp(               
    const float  x[],   
    const float  y[],     
    const short  n      
)
{
    short i;
    float suma;
    suma = 0.0f;

    for(i=0; i<n; i++) 
    {    
        suma += x[i] * y[i];
    } 
    return suma;
}
Run Code Online (Sandbox Code Playgroud)

我用昂纳雾在网络上提供的测试框架testp.

在这种情况下使用的数组是对齐的:

int n = 2048;
float* z2 = (float*)_mm_malloc(sizeof(float)*n, 64);
char *mem = (char*)_mm_malloc(1<<18,4096);
char *a = mem;
char *b = a+n*sizeof(float);
char *c = b+n*sizeof(float);

float *x = (float*)a;
float *y = (float*)b;
float *z = (float*)c;
Run Code Online (Sandbox Code Playgroud)

然后我调用函数dotp,n = 2048,repeat …

c optimization assembly sse micro-optimization

31
推荐指数
1
解决办法
1471
查看次数

使用未对齐缓冲区进行矢量化:使用VMASKMOVPS:根据未对齐计数生成掩码?或者根本不使用那个insn

gcc 5.3 with -O3 -mavx -mtune=haswellfor x86-64使得代码处理可能错位的代码变得非常笨重,例如:

// convenient simple example of compiler input
// I'm not actually interested in this for any real program
void floatmul(float *a) {
  for (int i=0; i<1024 ; i++)
    a[i] *= 2;
}
Run Code Online (Sandbox Code Playgroud)

clang使用未对齐的加载/存储指令,但是gcc执行标量intro/outro和对齐的向量循环:它剥离了第一个最多7个未对齐的迭代,将其完全展开为一个序列

    vmovss  xmm0, DWORD PTR [rdi]
    vaddss  xmm0, xmm0, xmm0      ; multiply by two
    vmovss  DWORD PTR [rdi], xmm0
    cmp     eax, 1
    je      .L13
    vmovss  xmm0, DWORD PTR [rdi+4]
    vaddss  xmm0, xmm0, xmm0
    vmovss …
Run Code Online (Sandbox Code Playgroud)

x86 assembly gcc sse avx

10
推荐指数
2
解决办法
960
查看次数

跳回矢量化余数循环的一些迭代

我手动矢量化循环并一次处理4个项目.项目总数可能不是4的倍数,所以我在主循环结束时留下了一些项目.我认为如果计数大于4并且重做某些项目是安全的,我可以使用相同的主矢量化循环执行剩余项目.例如,如果我需要处理10个项目,我可以在三次迭代中处理0123,4567,6789.我找不到任何对这种技术的引用.它是愚蠢但我不明白怎么样?

#include <stdint.h>
#include <stddef.h>

void inc(int32_t const* __restrict in, int32_t* out, size_t count)
{
    if (count < 4)
    {
        for (size_t i = 0; i < count; ++i)
            out[i] = in[i] + 42;
    }
    else
    {
        typedef int32_t v4i __attribute__ ((vector_size (16), aligned(4)));
        for (size_t i = 0;;)
        {
            for (; i + 4 <= count; i += 4)
            {
                (v4i&)out[i] = (v4i&)in[i] + 42;
            }
            if (i == count)
                break;
            i = count - 4;
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

c performance x86 assembly simd

8
推荐指数
1
解决办法
117
查看次数

标签 统计

assembly ×3

c ×2

sse ×2

x86 ×2

avx ×1

gcc ×1

micro-optimization ×1

optimization ×1

performance ×1

simd ×1