Merit do arredondamento ASM inline através da colocação de float na variável int
Eu herdei um pedaço de código bastante interessante:
inline int round(float a)
{
int i;
__asm {
fld a
fistp i
}
return i;
}
Meu primeiro impulso foi descartá-lo e substituir as chamadas por(int)std::round
(pré-C ++ 11, usariastd::lround
se aconteceu hoje), mas depois de um tempo comecei a me perguntar se poderia ter algum mérito, afinal ...
Os casos de uso para esta função são todos os valores em[-100, 100]
, entãoint8_t
seria grande o suficiente para conter o resultado.fistp
requer pelo menos uma variável de memória de 32 bits; portanto, menos deint32_t
é tão desperdiçado quanto mai
Agora, obviamente, converter o float para int não é a maneira mais rápida de fazer as coisas, pois o modo de arredondamento deve ser alterado paratruncate
, conforme o padrão, e depois depois. O C ++ 11 oferece ostd::lround
, que alivia esse problema em particular, mas ainda parece ser um desperdício, considerando que o valor passa float-> long-> int em vez de chegar diretamente onde deveri
or outro lado, com o ASM embutido na função, o compilador não pode otimizar a distâncii
em um registro (e mesmo que pudesse,fistp
espera uma variável de memória), entãostd::lround
não parece muito pior ...
A pergunta mais urgente que tenho é, porém, quão seguro é assumir (como essa função), que o modo de arredondamento será sempreround-to-nearest
, como obviamente faz (sem verificações). Comostd::lround
tem que garantir um certo comportamento independente do modo de arredondamento, essa suposição, enquanto durar, sempre parece fazer do ASM inline a melhor opçã
Além disso, não é muito claro para mim se o modo de arredondamento definido porstd::fesetround
e usado pelostd::lround
alternativostd::lrint
e o modo de arredondamento empregado nofistp
A instrução ASM é garantida para ser a mesma ou pelo menos síncron
ssas são minhas considerações, também conhecido como o que eu não sei para tomar uma decisão informada sobre a manutenção ou substituição da funçã
Agora, para as perguntas:
Seguindo uma visão mais informada dessas considerações ou das quais não pensei, parece aconselhável usar esta função?
Quão grande é o risco, se houver algum?
Existe um raciocínio para explicar por que não seria mais rápido do questd::lround
oustd::lrint
?
Pode ser melhorado ainda mais sem custo de desempenho?
Algum desses raciocínios muda se o programa foi compilado para x86-64?