<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xml" href="/cjs/screen.xsl" media="screen"?>
<lecture>

<meta>
  <maintitle>Python</maintitle>
  <author>Jiří Znamenáček</author>
  <title>Jak na rychlost – Numba</title>
  <date>2016-12-21</date>
  <link><!--a href="http://vyuka.ookami.cz" rel="external">http://vyuka.ookami.cz</a--></link>
  <!--
  <style>
    /* CSSka */
  </style>
  <use-math/>
  -->
</meta>
<!--
  „“–…
  ←→ ↑↓ ↔↕
  ↵ aneb &#x21B5; aneb \r aneb CR aneb CarriageReturn
-->


<slide title="Úvod">

    <p>
        <a href="http://numba.pydata.org" class="external"><strong>Numba</strong></a> patří mezi alternativní interpretry Python'u s několika dodanými velmi výraznými vylepšeními. Použít se dá v podstatě dvěma způsoby:
    </p>
    <ul>
        <li>
            méně často <!--(spíš asi skoro vůbec :-)--> pouze jako interpretr pythoního kódu;
        </li>
        <li>
            jako knihovna sloužící k relativně snadnému zrychlení pythoních kódů, obzvláště pokud používají knihovnu <em>Numpy</em>.
        </li>
    </ul>
    <p>
        Vývoj <em>Numby</em> probíhá dosti rychle, přesto mezi podporovanými <a href="http://numba.pydata.org/numba-doc/latest/reference/pysupported.html" class="external">pythoními</a> a <a href="http://numba.pydata.org/numba-doc/latest/reference/numpysupported.html" class="external">numpyovskými</a> vlastnostmi může zatím chybět to, co zrovna potřebujete. Ale za pokus to vždy stojí.
    </p>

</slide>
<slide title="Poznámka k instalaci">

    <p>
        Nainstalovat <em>Numbu</em> není vůbec jednoduché – mimo jiné vyžaduje instalaci správné verze <em>LLVM</em> a jeho pro potřeby Numby upraveného rozhraní pro Python <em>llvmlite</em> plus samozřejmě <em>Numpy</em> (se všemi jeho závislostmi) a ještě několik dalších balíčků.
    </p>
    <p>
        Kde se nezadaří klasické <code>pip install numba</code>, zabere téměř určitě <code>conda install numba</code> (musíte ovšem pracovat minimálně pod <a href="/materialy/python/packages/conda_overview.xml">Minicondou</a>).
    </p>
    <p>
        PS: Podpora CUDA se musí doinstalovat a nastavit zvlášť (viz <a href="https://github.com/numba/numba" class="external">oficiální dokumentace</a>). S <em>Condou</em> to jde jako vždy výrazně jednodušeji.
    </p>

</slide>
<slide title="„@jit“">

    <p>
        Mezi nejzajímavější prostředky, které <em>Numba</em> nabízí, patří dekorátor <strong><code>@jit</code></strong>. Jeho základní použití je triviální:
    </p>
    <example lang="python">
        from numba import jit

        @jit
        def funkce(parametr):
            ...
    </example>
    <p>
        <em>Numba</em> se v tomto případě pokusí vstupní i návratové typy odhadnout sama a odekorovanou funkci zJITovat. Ve většině případů je to asi to nejlepší (a rozhodně to nejjednodušší), co můžete udělat.
    </p>

</slide>
<slide title="„@jit“ s typovou anotací">

    <p>
        Nechcete-li z nejrůznějších důvodů nechat odhadování typů na <em>Numbě</em>, můžete použít <strong>typovou anotaci</strong>, kterou řeknete, o jaké typy se u dané funkce jedná. Jednoduchý příklad upravený <a href="http://numba.pydata.org/numba-doc/latest/user/jit.html#eager-compilation" class="external">podle dokumentace</a>:
    </p>
    <example lang="python">
        from numba import jit, int16

        @jit(int16(int16, int16))
        def fn(x, y):
            return x + y
    </example>
    <note>
        Zatímco <em>Numba</em> samotná se snaží být co nejobecnější, u vlastních kódů musíte vědět, co děláte, jinak vás čekají překvapení o něco dříve, než s obecným řešením:
        <example lang="python">
            >>> fn(1, 2)
            3

            >>> fn(2**15, 0)
            -32768
            >>> fn(2**15, -1)
            32767
        </example>
    </note>
    <p>
        PS: Anotace nemusí být úplná, můžete vynechat typ návratové hodnoty. Podobně se jich dá použít vícero (tedy vyjmenovat více možných <em>otisků funkce</em> pro různé typy), pak už ale záleží na jejich pořadí.
    </p>

</slide>
<slide title="„@jit(nopython=True)“">

    <p>
        <em>Numba</em> se pokusí odekorovanou funkci zJITovat nejvhodnějším možným způsobem (tzv. <em>nopython mode</em>), ale ne vždy se to podaří, v kterémžto případě automaticky spadne do mnohem pomalejšího – ale na druhou stranu zcela Python C API kompatibilního – módu kompilace <em>object mode</em>.
    </p>
    <p>
        Chcete-li uvedenému automatickému překladu předejít, stačí doplnit dekorátor na tvar <code>@jit(nopython=True)</code> – objeví-li <em>Numba</em> při kompilaci konstrukci, se kterou není optimálně proveditelná, místo přechodu na <em>object mode</em> vyhodí výjimku a zpracování kódu zastaví.
    </p>
    <note>
        Co pak provedete, je na vás. Ideální je pokusit se dekorovanou funkci upravit tak, aby šla zJITovat a <em>Numba</em> přestala házet výjimku, ale nemusí se to vždy snadno podařit.
    </note>

</slide>
<slide title="„@jit“ – souhrn">

    <p>
        Plná varianta dekorátoru <strong>@jit</strong> jest:
    </p>
    <example lang="python">
        @numba.jit(
            signature=None,
            nopython=False,
            nogil=False,
            cache=False,
            forceobj=False,
            locals={}
        )
    </example>
    <p>
        Odtud je mimo jiné vidět, proč může být typová anotace zadána beze jména parametru – je totiž první. Podobně přepínač <em>nopython</em> má – především asi pro ladicí účely – doplněk <em>forceobj</em>. A ty další:
    </p>
    <ul>
        <li>
            <code>nogil</code> – možnost vypnutí nechvalně proslulého <a href="http://vyuka/materialy/python/parallelism/overview.xml?slajd=3">GIL</a>u, ovšem se všemi důsledky z toho plynoucími (tedy pozor na paměť!);
        </li>
        <li>
            <code>cache</code> – možnost uložení již dříve zkompilovaných funkcí na disk;
            <notes>
                <note>
                    Může-li, skončí výsledek této kompilace v tradičním adresáři <code>__pycache__</code> vedle kódu.
                </note>
                <note>
                    Ne pro všechny funkce lze uložení provést – chcete-li vidět zprávu o neúspěchu, nastavte proměnnou prostředí <em>NUMBA_WARNINGS</em> na nenulovou hodnotu.
                </note>
            </notes>
        </li>
        <li>
            <code>locals</code> – může být použito pro vnucení typů lokálních proměnných funkce (ale nedoporučuje se používat).
        </li>
    </ul>
    <p>
    </p>

</slide>
<!--
    http://numba.pydata.org/numba-doc/latest/user/vectorize.html?highlight=guvectorize
    http://numba.pydata.org/numba-doc/latest/reference/jit-compilation.html#vectorized-functions-ufuncs-and-dufuncs
-->
<slide title="„@vectorize“">

    <p>
        TODO
    </p>
    <example lang="python">
    </example>

</slide>
<slide title="„@guvectorize“">

    <p>
        TODO
    </p>
    <example lang="python">
    </example>

</slide>
<slide title="">

    <p>
    </p>
    <example lang="python">
    </example>

</slide>


</lecture>
