相关疑难解决方法(0)

在L1缓存中获取Haswell的峰值带宽:仅获得62%

我试图在L1缓存中获得全部带宽,以便在Intel处理器上实现以下功能

float triad(float *x, float *y, float *z, const int n) {
    float k = 3.14159f;
    for(int i=0; i<n; i++) {
        z[i] = x[i] + k*y[i];
    }
}
Run Code Online (Sandbox Code Playgroud)

这是STREAM的三合一功能.

使用具有此功能的SandyBridge/IvyBridge处理器可获得约95%的峰值(使用NASM组装).但是,除非我展开循环,否则使用Haswell I仅达到峰值的62%.如果我展开16次,我得到92%.我不明白这一点.

我决定使用NASM在汇编中编写我的函数.装配中的主循环看起来像这样.

.L2:
    vmovaps         ymm1, [rdi+rax]
    vfmadd231ps     ymm1, ymm2, [rsi+rax]
    vmovaps         [rdx+rax], ymm1
    add             rax, 32
    jne             .L2
Run Code Online (Sandbox Code Playgroud)

在示例12.7-12.11 中的Agner Fog的优化组装手册中,他y[i] = y[i] +k*x[i]对Pentium M,Core 2,Sandy Bridge,FMA4和FMA3 做了几乎相同的事情(但是).我设法或多或少地自己重现了他的代码(实际上他在广播时在FMA3示例中有一个小错误).除FMA4和FMA3外,他为每个处理器的表格提供指令大小计数,融合操作,执行端口.我曾试图为FMA3制作这张桌子.

                                 ports
             size   ?ops-fused   0   1   2   3   4   5   6   7    
vmovaps      5      1                    ½   ½ …
Run Code Online (Sandbox Code Playgroud)

c memory assembly nasm fma

47
推荐指数
1
解决办法
7594
查看次数

在GCC中生成没有cmp指令的循环

我有许多紧凑的循环,我正在尝试使用GCC和内在函数进行优化.考虑例如以下功能.

void triad(float *x, float *y, float *z, const int n) {
    float k = 3.14159f;
    int i;
    __m256 k4 = _mm256_set1_ps(k);
    for(i=0; i<n; i+=8) {
        _mm256_store_ps(&z[i], _mm256_add_ps(_mm256_load_ps(&x[i]), _mm256_mul_ps(k4, _mm256_load_ps(&y[i]))));
    }
}
Run Code Online (Sandbox Code Playgroud)

这会产生这样的主循环

20: vmulps ymm0,ymm1,[rsi+rax*1]
25: vaddps ymm0,ymm0,[rdi+rax*1]
2a: vmovaps [rdx+rax*1],ymm0
2f: add    rax,0x20
33: cmp    rax,rcx
36: jne    20 
Run Code Online (Sandbox Code Playgroud)

但是cmp指令是不必要的.而不是具有rax在零开始和结束在sizeof(float)*n我们可以设置基指针(rsi,rdi,和rdx),以阵列的端部,并设置rax-sizeof(float)*n然后测试为零.我可以用我自己的汇编代码这样做

.L2  vmulps          ymm1, ymm2, [rdi+rax]
     vaddps          ymm0, ymm1, [rsi+rax]
     vmovaps         [rdx+rax], ymm0 …
Run Code Online (Sandbox Code Playgroud)

c optimization assembly gcc intrinsics

12
推荐指数
1
解决办法
847
查看次数

使用带AVX-512加载和存储的掩码寄存器时,是否存在因屏蔽元素无效访问而引发的错误?

当我做一个写掩码的AVX-512商店时,如下所示:

vmovdqu8 [rsi] {k1}, zmm0
Run Code Online (Sandbox Code Playgroud)

如果[rsi, rsi + 63]未映射的存储器的某些部分未被映射但是所有那些位置的写掩码为零(即,由于掩码实际上未修改数据),指令是否会发生故障.

另一种询问方式是这些AVX-512屏蔽存储是否具有类似的故障抑制能力,以便vmaskmov在AVX中引入.

x86 avx avx512

7
推荐指数
1
解决办法
407
查看次数

x86_64 - 汇编 - 循环条件和乱序

不是要求基准.

(如果是这样的话,我会自己做的.)


我的问题:

为方便起见,我倾向于避免间接/索引寻址模式.

作为替代,我经常使用立即,绝对或寄存器寻址.

代码:

; %esi has the array address. Say we iterate a doubleword (4bytes) array.
; %ecx is the array elements count
(0x98767) myloop:
    ... ;do whatever with %esi
    add $4, %esi
    dec %ecx
    jnz 0x98767;
Run Code Online (Sandbox Code Playgroud)

在这里,我们有一个序列化的组合(dec和jnz),它可以防止正常的乱序执行(依赖).

有没有办法避免/破坏dep?(我不是装配专家).

assembly loops x86-64 conditional-statements

4
推荐指数
1
解决办法
1070
查看次数

标签 统计

assembly ×3

c ×2

avx ×1

avx512 ×1

conditional-statements ×1

fma ×1

gcc ×1

intrinsics ×1

loops ×1

memory ×1

nasm ×1

optimization ×1

x86 ×1

x86-64 ×1