yad*_*dhu 1 c++ profiling avx avx2 perf
我试图使用perf工具来分析我的C++代码.实现包含带有SSE/AVX/AVX2指令的代码.除了该代码使用-O3 -mavx2 -march=native标志编译.我相信__memset_avx2_unaligned_erms函数是一个libc实现memset.perf表明这个功能有相当大的开销.函数名称表示内存未对齐,但在代码中我使用GCC内置宏显式对齐内存__attribute__((aligned (x)))可能是此函数有明显开销的原因以及为什么虽然内存明确对齐但调用了未对齐版本?
不,它没有. 这意味着glibc在该硬件上选择的memset策略是在小尺寸情况下不会试图完全避免对齐访问的策略.(glibc在动态链接器符号解析时选择一个memset实现,因此它在第一次调用后得到运行时调度而没有额外的开销.)
如果您的缓冲区实际上是对齐的并且大小是向量宽度的倍数,则所有访问都将对齐,并且基本上没有开销.(使用vmovdqu恰好在运行时对齐的指针与vmovdqa支持AVX的所有CPU 完全相同.)
对于大缓冲区,它仍然在主循环之前对齐指针,以防它未对齐,代价是一些额外的指令与仅适用于32字节对齐指针的实现相比.(但它看起来像是在rep stosb没有对齐指针的情况下使用它,如果它将会发生的话rep stosb.)
gcc + glibc没有特殊版本的memset,只能用对齐的指针调用.(或针对不同对齐保证的多个特殊版本).GLIBC的AVX2未对齐实现适用于对齐和未对齐输入.
它的定义是glibc/sysdeps/x86_64/multiarch/memset-avx2-unaligned-erms.S,它定义了几个宏(比如将矢量大小定义为32),然后是#includes "memset-vec-unaligned-erms.S".
源代码中的注释说:
/* memset is implemented as:
1. Use overlapping store to avoid branch.
2. If size is less than VEC, use integer register stores.
3. If size is from VEC_SIZE to 2 * VEC_SIZE, use 2 VEC stores.
4. If size is from 2 * VEC_SIZE to 4 * VEC_SIZE, use 4 VEC stores.
5. If size is more to 4 * VEC_SIZE, align to 4 * VEC_SIZE with
4 VEC stores and store 4 * VEC at a time until done. */
Run Code Online (Sandbox Code Playgroud)
主循环之前的实际对齐是在一些vmovdqu向量存储之后完成的(如果在实际对齐的数据上使用,则不会受到惩罚:https://agner.org/optimize/):
L(loop_start):
leaq (VEC_SIZE * 4)(%rdi), %rcx # rcx = input pointer + 4*VEC_SIZE
VMOVU %VEC(0), (%rdi) # store the first vector
andq $-(VEC_SIZE * 4), %rcx # align the pointer
... some more vector stores
... and stuff, including storing the last few vectors I think
addq %rdi, %rdx # size += start, giving an end-pointer
andq $-(VEC_SIZE * 4), %rdx # align the end-pointer
L(loop): # THE MAIN LOOP
VMOVA %VEC(0), (%rcx) # vmovdqa = alignment required
VMOVA %VEC(0), VEC_SIZE(%rcx)
VMOVA %VEC(0), (VEC_SIZE * 2)(%rcx)
VMOVA %VEC(0), (VEC_SIZE * 3)(%rcx)
addq $(VEC_SIZE * 4), %rcx
cmpq %rcx, %rdx
jne L(loop)
Run Code Online (Sandbox Code Playgroud)
因此,当VEC_SIZE = 32时,它将指针与128对齐.这是过度的; 缓存行是64个字节,实际上只是对齐矢量宽度应该没问题.
rep stos在具有ERMSB的CPU上,它还具有使能if 的阈值,缓冲区大小> 2kiB.(针对memcpy的增强型REP MOVSB).
| 归档时间: |
|
| 查看次数: |
906 次 |
| 最近记录: |