_ftol2_sse, existem opções mais rápidas?

Eu tenho código que chama muito

int myNumber = (int)(floatNumber); 

que ocupa, no total, cerca de 10% do tempo da minha CPU (de acordo com o profiler). Enquanto eu poderia deixar por aí, eu me pergunto se há opções mais rápidas, então eu tentei procurar por aí, e me deparei com

http://devmaster.net/forums/topic/7804-fast-int-float-conversion-routines/ http://stereopsis.com/FPU.html

Eu tentei implementar a function Real2Int () dada lá, mas isso me dá resultados errados e funciona mais devagar. Agora eu me pergunto, existem implementações mais rápidas para valores double / float de piso para números inteiros, ou a versão SSE2 é a mais rápida possível? As páginas que encontrei estão um pouco atrasadas, por isso pode estar desatualizado, e o STL mais novo é mais rápido.

A implementação atual faz:

 013B1030 call _ftol2_sse (13B19A0h) 013B19A0 cmp dword ptr [___sse2_available (13B3378h)],0 013B19A7 je _ftol2 (13B19D6h) 013B19A9 push ebp 013B19AA mov ebp,esp 013B19AC sub esp,8 013B19AF and esp,0FFFFFFF8h 013B19B2 fstp qword ptr [esp] 013B19B5 cvttsd2si eax,mmword ptr [esp] 013B19BA leave 013B19BB ret 

Perguntas relacionadas que encontrei:

Flutuante rápido para conversão int e precisão de ponto flutuante em ARM (iPhone 3GS / 4)

Qual é o caminho mais rápido para converter float para int em x86

Como ambos são antigos ou baseados em ARM, gostaria de saber se existem maneiras atuais de fazer isso. Note que a melhor conversão é aquela que não acontece, mas eu preciso ter, então isso não será possível.

Vai ser difícil de bater se você estiver alvejando hardware x86 genérico. O tempo de execução não tem certeza de que a máquina de destino possui uma unidade SSE. Se assim fosse, poderia fazer o que o compilador x64 faz e inline um opcode cvttss2si . Mas, como o tempo de execução precisa verificar se uma unidade SSE está disponível, você fica com a implementação atual. É isso que a implementação do ftol2_sse faz. E mais, ele passa o valor em um registrador x87 e, em seguida, o transfere para um registrador SSE se uma unidade SSE estiver disponível.

Você poderia dizer ao compilador x86 para direcionar máquinas que possuem unidades SSE. Em seguida, o compilador realmente emitirá um código de operação cvttss2si simples em linha. Isso vai ser o mais rápido que puder. Mas se você executar o código em uma máquina mais antiga, ele falhará. Talvez você possa fornecer duas versões, uma para máquinas com SSE e outra para aquelas sem.

Isso não vai ganhar muito de você. É só para evitar toda a sobrecarga de ftol2_sse que acontece antes de você realmente chegar ao opcode cvttss2si que faz o trabalho.

Para alterar as configurações do compilador do IDE, use Projeto> Propriedades> Propriedades de configuração> C / C ++> Geração de código> Ativar conjunto de instruções aprimorado. Na linha de comando, é / arch: SSE ou / arch: SSE2.

Para o double eu não acho que você será capaz de melhorar os resultados muito, mas se você tem um monte de float s para converter isso usando uma conversão embalada poderia ajudar, o seguinte é código nasm :

 global _start section .data align 16 fv1: dd 1.1, 2.5, 2.51, 3.6 section .text _start: cvtps2dq xmm1, [fv1] ; Convert four 32-bit(single precision) floats to 32-bit(double word) integers and place the result in xmm1 

Deve haver código intrínseco que permita fazer a mesma coisa de maneira mais fácil, mas não estou tão familiarizado com o uso de bibliotecas intrínsecas. Embora você não esteja usando o gcc, este artigo Auto-vectorization with gcc 4.7 é um abridor de olho sobre quão difícil pode ser conseguir que o compilador gere um bom código vetorizado.

Se você precisa de velocidade e uma grande base de máquinas de destino, é melhor introduzir uma versão SSE rápida de todos os seus algoritmos, além de uma versão genérica – e escolher os algoritmos a serem executados em um nível muito mais alto.

Isso também significa que também a ABI é otimizada para SSE; e que você pode vetorizar o cálculo quando disponível e que também a lógica de controle é otimizada para a arquitetura.

btw. até mesmo FLD; FIST FLD; FIST seqüência FLD; FIST deve levar mais que ~ 7 ciclos de clock no Pentium.