我正在尝试比较带有-O3标志的标量代码和Intel AVX(SIMD)代码的性能。
运行程序后,我发现它们之间存在巨大的性能差异。
我使用4个功能:
*总和
*数
*分钟
*最大
对于所有标量执行,我检索到的结果时间为0.000001秒(平均,每种情况下执行11次),而AVXSum,AVXMin,AVXMax的结果时间为0.043958秒(计数情况下,两次执行都得到相同的快速结果)。
我试图深入研究标量函数的汇编代码。令我惊讶的是,我发现gcc会为ScalarSum,ScalarCount,ScalarMin,ScalarMax生成相同的汇编代码。
由于发生RAW依赖关系,所以我期望执行时间会有所延迟。仔细查看分支未命中数,它们非常接近(即:AVXMin为772,548,846个分支丢失,平均为0.044221sec,ScalarMin为772,656,995个分支丢失平均为0.000000秒)。
输入(关系)是1024 * 1024 * 1024个元素的数组(rel_size)。 在主函数中,我初始化并随机化输入数组(rand()为用户,并实现了Fisher Yates算法)。我相信不会进行编译时间计算,但是我无法解释如此大的性能差异。
下面,我将为标量大小写附加生成的汇编代码(正如我提到的,所有情况都相同)。此外,我附加了AVXMin和ScalarMin C代码。
.file "scalarMin.c"
.section .text.unlikely,"ax",@progbits
.LCOLDB1:
.text
.LHOTB1:
.p2align 4,,15
.globl scalar_min
.type scalar_min, @function
scalar_min:
.LFB38:
.cfi_startproc
pushq %rbx
.cfi_def_cfa_offset 16
.cfi_offset 3, -16
call clock
movq %rax, %rbx
call clock
pxor %xmm0, %xmm0
subq %rbx, %rax
popq %rbx
.cfi_def_cfa_offset 8
cvtsi2sdq %rax, %xmm0
divsd .LC0(%rip), %xmm0
ret
.cfi_endproc
.LFE38:
.size scalar_min, .-scalar_min
.section .text.unlikely
.LCOLDE1:
.text
.LHOTE1:
.section .rodata.cst8,"aM",@progbits,8
.align 8
.LC0:
.long 0
.long 1093567616
.ident "GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.10) 5.4.0 20160609"
.section .note.GNU-stack,"",@progbits
Intel AVX Min功能:
double avx_min(int32_t** relation, int32_t rel_size){
clock_t t;
__m256i input_buffer;
__m256i min = _mm256_set_epi32(INT32_MAX, INT32_MAX, INT32_MAX, INT32_MAX, INT32_MAX, INT32_MAX, INT32_MAX, INT32_MAX);
t = clock();
for(int i = 0 ; i < rel_size ; i += 8){
input_buffer = _mm256_stream_load_si256((__m256i*)&(*relation)[i]);
min = _mm256_min_epi32(min, input_buffer);
}
t = clock() - t;
return ((double) t) /CLOCKS_PER_SEC;
}
标量最小值功能:
double scalar_min(int32_t** relation, int32_t rel_size){
clock_t t;
int32_t min = INT32_MAX;
t = clock();
for(int i = 0 ; i < rel_size ; i++){
if( (*relation)[i] < min ){
min = (*relation)[i];
}
}
t = clock() - t;
return ((double) t) /CLOCKS_PER_SEC;
}
在此先感谢您的帮助:)