Autor Zpráva
Oxidián
Profil *
Tak teď si asi říkáte, proč chci napsat funkci ceil a floor. Protože jsem před chvílí zjistil, že volání jakékoliv funkce uvnitř smyčky (například při vypisování pixelů obrázku) náramně ubírá na výkonu. Tedy by bylo možné získat lepší výkon, když bych místo volání funkce ze smyčky použil vlastní algoritmus. Jenže nevím jak nato. Celý kód jsem již testoval ve předchozím vlákně o nalezení nejmenší a největší hodnoty. Už jsem dal pryč funkci round() a nastalo další zrychlení. Tak proč to neurychlit ještě více?

$R = round($varR * 255);
$G = round($varG * 255);
$B = round($varB * 255);
jsem nahradil za
$R = $varR * 255 < 0.0 ? ceil($varR * 255 - 0.5) : floor($varR * 255 + 0.5);
$G = $varG * 255 < 0.0 ? ceil($varG * 255 - 0.5) : floor($varG * 255 + 0.5);
$B = $varG * 255 < 0.0 ? ceil($varB * 255 - 0.5) : floor($varB * 255 + 0.5);
juriad
Profil
Docela dobře funguje:
function r($x) {
        return (int) ($x + 0.5) - ($x < 0);
}
Ale dělá to chyby kolem polovin a v blízkosti nuly. Otázkou je, jak moc to vadí?

volání funkce round: 4.0317828655243
volání funkce r: 5.566967010498
inline výpočet: 3.4816009998322
abc
Profil
nevím, nakolik to bude rychlejší (možná to bude spíš pomalejší), ale pokud jsou výsledkem čísla od 0-255, tak by k tomu asi šlo přistupovat jako ke stringu a když narazíš na ., tak máš zaokrouhleno dolu a podle dalších čísel za desetinnou tečkou případně přičítat 1
Oxidián
Profil *
juriad:
Co se týče rychlosti není v tom rozdíl, tvoje varianta je možná nepatrně pomalejší než když použiju volání ceil a floor. Možná to spomaluje ten casting.

po odstranění funkce round:
A)
1.394
1.455
1.416
B)
2.533
2.652
2.64
2.675

Juriadova variace:
A)
1.443
1.44
1.39
B)
2.681
2.688
2.78
2.717
Joker
Profil
Oxidián:
Jestli je nutné to optimalizovat až do takové míry, zkusil bych to místo PHP napsat rovnou v Céčku.
juriad
Profil
Mně na mojí mašině vychází jiné statistiky:
volání round: 44.26890707016
volání ceil_floor: 106.42230200768
volání r: 58.501924037933
inline r: 36.389965057373
inline r bez korekce: 22.217283964157
floor: 58.362727880478
inline r bez přetypování: 25.081015110016
pouze přičtení 0.5: 17.573384046555
inline floor & ceil: 64.921782016754
Zvýrazněné počítají zaokrouhlení. Ostatní slouží pro porovnání, jsou různě osekané.

Jedná se o:
Linux judy 3.14.6-1-ARCH #1 SMP PREEMPT Sun Jun 8 10:08:38 CEST 2014 x86_64 GNU/Linux
PHP 5.5.13 (cli) (built: May 29 2014 05:46:58)
Oxidián
Profil *
Já testoval jen 67500 cyklů v rámci svého obrázku a v rámci celého programu na vygenerování obrázku, kolik to trvá dohromady.


A počítám na tři místa což je rychlejší. Ale nevím jaký to má vliv na přesnost barev při převodu na hsv. Protože já okem žádný rozdíl nevidím, ale nezkoušel jsem dělat žádné úpravy na fotce. Jestli tam někde náhodou je odstín 61 místo 60 apod. tak to poznat nebude.
juriad
Profil
Můj poslední benchmark probíhal takto:
$r=50000000;
echo "volání XXX: ";
$t =microtime(true);
for ($i = -$r; $i<$r; $i+=0.3) {
        # sem jsem dal testovaný kód
}
echo microtime(true) - $t;
echo "\n";
Počítalo se tedy 333 milionů cyklů. Měřil jsem tedy jen výkon zaokrouhlování, nic jiného.

Pokud skutečně v tvém případě je volání floor nebo ceil podle ternárního operátoru rychlejší, tak v mém případě není. Jedná se o řádky „inline r“ a „inline flloor & ceil“. Je to dokonce v mém případě horší než volání funkce round, které je u mě dost rychlé.


Oxidián:
Jak jsi zjistil, že počítáš na 3 místa? O tom vůbec nevím, že by to šlo nastavit.

PHP, pokud vím, má jediný typ pro čísla s plovoucí desetinnou čárkou - tento typ je interně realizován jako double, který je známý z jiných jazyků.
Jakákoli jiná reprezentace desetinných čísel musí být nutně pomalejší.
Neprovádíš náhodou nějaké chujoviny se stringama?
Oxidián
Profil *
juriad:
V php.ini
; The number of significant digits displayed in floating point numbers.
precision = 12
nebo
ini_set("precision", 4);

Se stringama vůbec nepracuju.
pepiik
Profil *
juriad: tvoje funkce počíta špatně
$x = -0.4;
round($x); // -0
r($x);        // -1
Joker
Profil
pepiik:
Protože round, floor a ceil jsou tři různé způsoby zaokrouhlení.
juriad
Profil
pepiik:
Máš pravdu, špatně jsem to testoval. Chyba byla u argumentů s hodnotou mezi -0.5 a 0.
Oprava:
function r($x) {
        return (int) ($x + 0.5) - ($x <= -0.5);
}
1Pupik1989
Profil
Já používání následující:

round($n) === ($n + 0.5) >> 0;
ceil($n) === ($n + 1) >> 0;
floor($n) === $n >> 0;

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: