我在Skylake 6700HQ的GCC 4.8 -O2
编译了这个程序。
当我使用float
数据类型时,总执行时间为0.000176
秒。当我将float
更改为int
时,总时间为0.000026
(快约7倍)。我不知道造成这种差异的原因。相关问题:assembly output O3
我在Geany IDE构建命令gcc -Wall -march=native -O2 -o "%e" "%f"
中使用此命令。我还尝试了-O3
和-Ofast
,但这些都没有解决问题。
我还阅读this question,但此float
和int
实施之间存在太多差异。由于此float
实现比相应的int
实现慢7倍,因此这不是重复的问题
#include <stdio.h>
#include <time.h>
float a[32][32]
, t[32][32]
, c_result[32][32]
, c_tra[32][32] ;
int main()
{
int w = 10000;
int i, j, k, temp;
struct timespec tStart, tEnd;
double tTotal , tBest=10000;
do{
clock_gettime(CLOCK_MONOTONIC,&tStart);
for( i = 0; i < 32; i++){
for( j =0 ; j < 32; j++){
temp=0;
for( k = 0 ;k < 32; k++) {
temp += a[i][k] * c_tra[j][k];
}
c_result[i][j]= temp;
}
}
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--);
printf(" The best time: %lf sec\n",tBest);
return 0;
}
是int
数据类型的汇编输出:
.file "floatMULm.c"
.section .rodata.str1.8,"aMS",@progbits,1
.align 8
.LC2:
.string " The best time: %lf sec in %d repetition for %dX%d matrix\n"
.section .text.startup,"ax",@progbits
.p2align 4,,15
.globl main
.type main, @function
main:
.LFB24:
.cfi_startproc
subq $40, %rsp
.cfi_def_cfa_offset 48
movl $1, %edi
movq %rsp, %rsi
call clock_gettime
xorl %esi, %esi
.L2:
xorl %r8d, %r8d
.p2align 4,,10
.p2align 3
.L7:
movq %r8, %rdi
xorl %eax, %eax
xorl %ecx, %ecx
salq $5, %rdi
.p2align 4,,10
.p2align 3
.L5:
movl a(%rsi,%rax), %edx
imull c_tra(%rdi,%rax), %edx
addq $4, %rax
addl %edx, %ecx
cmpq $128, %rax
jne .L5
movl %ecx, c_result(%rsi,%r8)
addq $4, %r8
cmpq $128, %r8
jne .L7
subq $-128, %rsi
cmpq $4096, %rsi
jne .L2
leaq 16(%rsp), %rsi
movl $1, %edi
call clock_gettime
movq 24(%rsp), %rax
subq 8(%rsp), %rax
movl $32, %r8d
movl $32, %ecx
movl $10000, %edx
movl $.LC2, %esi
movl $1, %edi
vcvtsi2sdq %rax, %xmm1, %xmm1
movq 16(%rsp), %rax
subq (%rsp), %rax
vcvtsi2sdq %rax, %xmm0, %xmm0
movl $1, %eax
vdivsd .LC1(%rip), %xmm1, %xmm1
vaddsd %xmm0, %xmm1, %xmm0
vminsd .LC0(%rip), %xmm0, %xmm0
call __printf_chk
xorl %eax, %eax
addq $40, %rsp
.cfi_def_cfa_offset 8
ret
.cfi_endproc
.LFE24:
.size main, .-main
.comm c_tra,4096,32
.comm c_result,4096,32
.comm t,4096,32
.comm a,4096,32
.section .rodata.cst8,"aM",@progbits,8
.align 8
.LC0:
.long 0
.long 1086556160
.align 8
.LC1:
.long 0
.long 1104006501
.ident "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.1) 4.8.4"
.section .note.GNU-stack,"",@progbits
这适用于float
:
.file "floatMULm.c"
.section .rodata.str1.8,"aMS",@progbits,1
.align 8
.LC2:
.string " The best time: %lf sec in %d repetition for %dX%d matrix\n"
.section .text.startup,"ax",@progbits
.p2align 4,,15
.globl main
.type main, @function
main:
.LFB24:
.cfi_startproc
subq $40, %rsp
.cfi_def_cfa_offset 48
movl $1, %edi
movq %rsp, %rsi
call clock_gettime
xorl %ecx, %ecx
.L2:
xorl %edi, %edi
.p2align 4,,10
.p2align 3
.L7:
movq %rdi, %rsi
xorl %eax, %eax
xorl %edx, %edx
salq $5, %rsi
.p2align 4,,10
.p2align 3
.L5:
vcvtsi2ss %edx, %xmm0, %xmm0
vmovss a(%rcx,%rax), %xmm2
vfmadd231ss c_tra(%rsi,%rax), %xmm2, %xmm0
addq $4, %rax
vcvttss2si %xmm0, %edx
cmpq $128, %rax
jne .L5
vcvtsi2ss %edx, %xmm0, %xmm0
vmovss %xmm0, c_result(%rcx,%rdi)
addq $4, %rdi
cmpq $128, %rdi
jne .L7
subq $-128, %rcx
cmpq $4096, %rcx
jne .L2
leaq 16(%rsp), %rsi
movl $1, %edi
call clock_gettime
movq 24(%rsp), %rax
subq 8(%rsp), %rax
movl $32, %r8d
movl $32, %ecx
movl $10000, %edx
movl $.LC2, %esi
movl $1, %edi
vcvtsi2sdq %rax, %xmm1, %xmm1
movq 16(%rsp), %rax
subq (%rsp), %rax
vcvtsi2sdq %rax, %xmm0, %xmm0
movl $1, %eax
vdivsd .LC1(%rip), %xmm1, %xmm1
vaddsd %xmm0, %xmm1, %xmm0
vminsd .LC0(%rip), %xmm0, %xmm0
call __printf_chk
xorl %eax, %eax
addq $40, %rsp
.cfi_def_cfa_offset 8
ret
.cfi_endproc
.LFE24:
.size main, .-main
.comm c_tra,4096,32
.comm c_result,4096,32
.comm t,4096,32
.comm a,4096,32
.section .rodata.cst8,"aM",@progbits,8
.align 8
.LC0:
.long 0
.long 1086556160
.align 8
.LC1:
.long 0
.long 1104006501
.ident "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.1) 4.8.4"
.section .note.GNU-stack,"",@progbits
答案 0 :(得分:3)
问题是浮点版本的内部循环:
.L5:
vcvtsi2ss %edx, %xmm0, %xmm0
vmovss a(%rcx,%rax), %xmm2
vfmadd231ss c_tra(%rsi,%rax), %xmm2, %xmm0
addq $4, %rax
vcvttss2si %xmm0, %edx
cmpq $128, %rax
jne .L5
由于temp
中的main()
类型为int
(对应于程序集中的%edx
),因此必须在{{1}之间来回转换值和循环中的float
。根据{{3}},int
和CVTSI2SS
每个在Skylake上都有6个周期延迟。此外,转换是在依赖链中,因此无序和超标量执行在这种情况下没有多大帮助。
将CVT(T)SS2SI
main()
int temp
更改为float temp
会删除这些转换。