tecnicas site realizarse page optimizacion off hacer google definición define debe como auditoria antes c++ performance

c++ - site - seo off page definición



¿Por qué sin/cos son más lentos cuando las optimizaciones están habilitadas? (2)

AFAIK es porque las computadoras trabajan con doble precisión de forma nativa. Usar float requiere conversiones ''.

Después de leer una pregunta relacionada con la ejecución de sin / cos ( ¿Por qué es std :: sin () y std :: cos () más lento que sin () y cos ()? Cosa rara: si llamo sin / cos con un valor flotante, es mucho más lento que con el doble cuando se compila con optimización.

#include <cmath> #include <cstdio> const int N = 4000; float cosine[N][N]; float sine[N][N]; int main() { for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { float ang = i*j*2*M_PI/N; cosine[i][j] = cos(ang); sine[i][j] = sin(ang); } } }

Con el código anterior obtengo:

Con -O0: 2.402s

Con -O1: 9.004s

Con -O2: 9.013s

Con -O3: 9.001s

Ahora si me cambio

float ang = i*j*2*M_PI/N;

A

double ang = i*j*2*M_PI/N;

Yo obtengo:

Con -O0: 2.362s

Con -O1: 1.188s

Con -O2: 1.197s

Con -O3: 1.197s

¿Cómo puede la primera prueba ser más rápida sin optimizaciones?

Estoy usando g ++ (Ubuntu / Linaro 4.5.2-8ubuntu4) 4.5.2, 64 bits.

EDITAR: Se cambió el título para describir mejor el problema.

EDITAR: Código de montaje añadido

Montaje para la primera prueba con O0:

.file "main.cpp" .globl cosine .bss .align 32 .type cosine, @object .size cosine, 64000000 cosine: .zero 64000000 .globl sine .align 32 .type sine, @object .size sine, 64000000 sine: .zero 64000000 .text .globl main .type main, @function main: .LFB87: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 movq %rsp, %rbp .cfi_offset 6, -16 .cfi_def_cfa_register 6 subq $16, %rsp movl $0, -4(%rbp) jmp .L2 .L5: movl $0, -8(%rbp) jmp .L3 .L4: movl -4(%rbp), %eax imull -8(%rbp), %eax addl %eax, %eax cvtsi2sd %eax, %xmm0 movsd .LC0(%rip), %xmm1 mulsd %xmm1, %xmm0 movsd .LC1(%rip), %xmm1 divsd %xmm1, %xmm0 unpcklpd %xmm0, %xmm0 cvtpd2ps %xmm0, %xmm0 movss %xmm0, -12(%rbp) movss -12(%rbp), %xmm0 cvtps2pd %xmm0, %xmm0 call cos unpcklpd %xmm0, %xmm0 cvtpd2ps %xmm0, %xmm0 movl -8(%rbp), %eax cltq movl -4(%rbp), %edx movslq %edx, %rdx imulq $4000, %rdx, %rdx leaq (%rdx,%rax), %rax movss %xmm0, cosine(,%rax,4) movss -12(%rbp), %xmm0 cvtps2pd %xmm0, %xmm0 call sin unpcklpd %xmm0, %xmm0 cvtpd2ps %xmm0, %xmm0 movl -8(%rbp), %eax cltq movl -4(%rbp), %edx movslq %edx, %rdx imulq $4000, %rdx, %rdx leaq (%rdx,%rax), %rax movss %xmm0, sine(,%rax,4) addl $1, -8(%rbp) .L3: cmpl $3999, -8(%rbp) setle %al testb %al, %al jne .L4 addl $1, -4(%rbp) .L2: cmpl $3999, -4(%rbp) setle %al testb %al, %al jne .L5 movl $0, %eax leave .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE87: .size main, .-main .section .rodata .align 4 .type _ZL1N, @object .size _ZL1N, 4 _ZL1N: .long 4000 .align 8 .LC0: .long 1413754136 .long 1074340347 .align 8 .LC1: .long 0 .long 1085227008 .ident "GCC: (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2" .section .note.GNU-stack,"",@progbits

Montaje para la primera prueba con O3:

.file "main.cpp" .text .p2align 4,,15 .globl main .type main, @function main: .LFB121: .cfi_startproc pushq %r15 .cfi_def_cfa_offset 16 xorl %r15d, %r15d .cfi_offset 15, -16 pushq %r14 .cfi_def_cfa_offset 24 movl $cosine+16000, %r14d .cfi_offset 14, -24 pushq %r13 .cfi_def_cfa_offset 32 xorl %r13d, %r13d .cfi_offset 13, -32 pushq %r12 .cfi_def_cfa_offset 40 pushq %rbp .cfi_def_cfa_offset 48 pushq %rbx .cfi_def_cfa_offset 56 subq $24, %rsp .cfi_def_cfa_offset 80 .p2align 4,,10 .p2align 3 .L2: movslq %r15d, %rbp .cfi_offset 3, -56 .cfi_offset 6, -48 .cfi_offset 12, -40 movl %r13d, %r12d movl $0x3f800000, %edx imulq $16000, %rbp, %rbp xorl %eax, %eax leaq cosine(%rbp), %rbx addq $sine, %rbp jmp .L5 .p2align 4,,10 .p2align 3 .L3: movl %r12d, %eax leaq 8(%rsp), %rsi leaq 12(%rsp), %rdi subl %r13d, %eax cvtsi2sd %eax, %xmm0 mulsd .LC2(%rip), %xmm0 divsd .LC3(%rip), %xmm0 unpcklpd %xmm0, %xmm0 cvtpd2ps %xmm0, %xmm0 call sincosf movl 8(%rsp), %edx movl 12(%rsp), %eax .L5: movl %edx, (%rbx) addq $4, %rbx movl %eax, 0(%rbp) addl %r13d, %r12d addq $4, %rbp cmpq %r14, %rbx jne .L3 addl $1, %r15d addl $2, %r13d leaq 16000(%rbx), %r14 cmpl $4000, %r15d jne .L2 addq $24, %rsp .cfi_def_cfa_offset 56 xorl %eax, %eax popq %rbx .cfi_def_cfa_offset 48 popq %rbp .cfi_def_cfa_offset 40 popq %r12 .cfi_def_cfa_offset 32 popq %r13 .cfi_def_cfa_offset 24 popq %r14 .cfi_def_cfa_offset 16 popq %r15 .cfi_def_cfa_offset 8 ret .cfi_endproc .LFE121: .size main, .-main .globl cosine .bss .align 32 .type cosine, @object .size cosine, 64000000 cosine: .zero 64000000 .globl sine .align 32 .type sine, @object .size sine, 64000000 sine: .zero 64000000 .section .rodata.cst8,"aM",@progbits,8 .align 8 .LC2: .long 1413754136 .long 1074340347 .align 8 .LC3: .long 0 .long 1085227008 .ident "GCC: (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2" .section .note.GNU-stack,"",@progbits


Aquí hay una posibilidad:

En C, cos es doble precisión y cosf es precisión simple. En C ++, std::cos tiene sobrecargas tanto para doble como para simple.

No estás llamando std::cos . Si <cmath> no sobrecarga también ::cos (que yo sepa, no es obligatorio), entonces solo está llamando a la función de doble precisión C. Si este es el caso, entonces estás sufriendo el costo de la conversión entre float, double y back.

Ahora, algunas bibliotecas estándar implementan cos(float x) como (float)cos((double)x) , así que incluso si está llamando a la función float , es posible que todavía esté haciendo conversiones detrás de escena.

Sin embargo, esto no debería explicar una diferencia de rendimiento de 9x.