Vraag Hoe duur is het om tussen int en double te converteren?


Ik zie vaak code die ints converteert naar doubles naar ints om te verdubbelen en weer terug te gaan (soms om goede redenen, soms niet), en het kwam me gewoon voor dat dit een "verborgen" kost in mijn programma leek. Laten we aannemen dat de conversiemethode truncatie is.

Dus, hoe duur is het? Ik ben er zeker van dat dit varieert afhankelijk van de hardware, dus laten we uitgaan van een nieuwe Intel-processor (misschien, als je wilt, hoewel ik alles neem). Sommige statistieken waarin ik geïnteresseerd zou zijn (hoewel een goed antwoord niet allemaal hoeft te zijn):

  1. # gegenereerde instructies
  2. Aantal gebruikte cycli
  3. Relatieve kosten in vergelijking met elementaire rekenkundige bewerkingen

Ik zou ook aannemen dat de manier waarop we de impact van een langzame conversie het meest acuut zouden ervaren, zou zijn met betrekking tot energieverbruik in plaats van de uitvoeringssnelheid, gezien het verschil in het aantal berekeningen dat we elke seconde kunnen uitvoeren in verhouding tot hoeveel gegevens daadwerkelijk kunnen aankomen bij de CPU elke seconde.


12
2018-02-23 06:55


oorsprong


antwoorden:


Dit is wat ik zelf kon opgraven:

  1. Toen ik bekijk de gegenereerde assembly van clang en gcc lijkt het op de cast int naar doublekomt het neer op één instructie: cvttsd2si. Van double naar int haar cvtsi2sdl op clang, cvtsi2sd op gcc. Dus ik veronderstel dat de vraag wordt: wat zijn de kosten van die?
  2. De Intel 64 en IA-32 architecturen optimalisatie referentiehandleiding zegt die kosten van de cvttsd2si instructie is 5 latency (zie bijlage C-16). Ik kan geen referentie vinden voor cvtsi2sdl, maar cvtsi2sd, afhankelijk van uw architectuur, heeft latency variërend van 1 op Silvermont tot meer als 7-16 op verschillende andere architecturen. De handleiding definieert de wachttijd als: "Het aantal klokcycli dat vereist is voor de uitvoeringskern om de uitvoering van alle μops die een instructie vormen te voltooien."
  3. Dezelfde handleiding zegt dat een add instructie kost 1 latentie en een mul kosten 3-4 (bijlage C-27)

Het antwoord komt dus neer op: 1) Het is hardware geoptimaliseerd en de compiler maakt gebruik van de hardware-machines. 2) Het kost slechts een beetje meer dan een vermenigvuldiging doet in termen van het aantal cycli in de ene richting, en een zeer variabel bedrag in de andere (afhankelijk van uw architectuur). De kosten ervan zijn niet gratis en ook niet absurd, maar verdienen waarschijnlijk meer aandacht, gezien het gemak van het schrijven van code die de kosten op een niet voor de hand liggende manier met zich meebrengt.


22
2018-02-23 06:55



Natuurlijk hangt dit soort vraag af van de exacte hardware en zelfs van de modus.

Op x86 mijn i7 bij gebruik in de 32-bits modus met standaardopties (gcc -m32 -O3) de conversie van int naar double is vrij snel, het tegenovergestelde is in plaats daarvan langzamer omdat de C-norm een ​​absurde regel oplegt (afkappen van decimalen).

Deze manier van afronden is slecht voor zowel wiskunde als voor hardware en vereist dat de FPU overschakelt naar deze speciale afrondingsmodus, de truncatie uitvoert en teruggaat naar een normale afrondingsmethode.

Als je snelheid nodig hebt, doe je de float-> int-conversie met de simpele fistp instructie is sneller en ook veel beter voor berekeningsresultaten, maar vereist enige inline-assemblage.

inline int my_int(double x)
{
  int r;
  asm ("fldl %1\n"
       "fistpl %0\n"
       :"=m"(r)
       :"m"(x));
  return r;
}

is meer dan 6 keer sneller dan naïef x = (int)y; conversie (en heeft geen voorkeur voor 0).

Dezelfde processor, die in de 64-bits modus wordt gebruikt, heeft echter geen snelheidsproblemen en gebruikt de fistp code maakt de code eigenlijk iets langzamer.

Blijkbaar hebben de hardware-jongens het slechte afrondingsalgoritme direct in hardware opgegeven en geïmplementeerd (slechte code kan nu snel worden uitgevoerd).


3
2018-02-23 07:08