nortikin / sverchok

Sverchok
http://nortikin.github.io/sverchok/
GNU General Public License v3.0
2.23k stars 232 forks source link

Can we use Numba?... #2646

Closed portnov closed 2 years ago

portnov commented 4 years ago

This is yet another topic about performance. Link: http://numba.pydata.org/ Numba is a jit-compiler for python. I managed to install it with pip into blender's python, and on simple examples like

from numba import jit

@jit
def main():
  result = 0
  for i in range(1000000):
    result = result + i
  return result

it gives about 10x boost.

While this looks very promising, it has one problem: it can't effectively handle the switch from JIT-ed code into not-jit-ed. I.e. if you make a call from function marked with @jit to function which is not jit-ed, Numba will switch back to plain interpretation mode and there will no boost anymore. For example, you can't call functions from python standard packages... one exclusion is numpy: Numba is especially aware of numpy and works effectively with numpy calls.

So. Do we have complex places, that require speedup and do all work by theirselves, without calling for external functions/libraries (except for numpy)?

I tried with "bend along surface" node — no luck, there is a lot of calls from it to outside and then again into node...

zeffii commented 4 years ago

i think inset_specials is self contained.

zeffii commented 4 years ago

and uv_connections

portnov commented 4 years ago

https://stackoverflow.com/questions/56792853/numba-v0-44-cannot-reflect-element-of-reflected-container/56794390

Numba as of 0.44 does not support list of lists as inputs to functions in nopython mode.

:( we use nested lists a lot. So it seems there is no easy way: one cannot just put @jit everywhere and be happy. Code has to be specifically written for numba.

portnov commented 4 years ago

(more specifically, it does support nested lists, it just switches back to interpreting mode, so becomes useless).

zeffii commented 4 years ago

if it doesn't work on nested lists, would it accept "unrolled lists" , with information about nesting, then use that representation in the decorated function?

zeffii commented 4 years ago

maybe the preprocessing step of "flattening" would take up more time than saved by the numba stuff. hehe..

portnov commented 4 years ago

Yes, it'll work with "unrolled" lists. Also it will work with numpy arrays.

alessandro-zomparelli commented 4 years ago

Hi guys, I'm using Numba in the Tissue Reaction-Diffusion code, and for me it gave a boost of 500 times @_@ It seems to work better with python for loops rather than numpy operations and allows parallel execution. It's insane. I highly recommedn to use it in some part of the code. It works great with numercial operations/expressions, but doesn't allow to use calls from other modules. So maybe it could be used for creating some low level optimized functions to call from the different nodes (addition, multiplication, power, frequently used expressions, etc...). Also, I would recommend to avoid nested list in general, in my opinion they are not the most efficient way to handle complex data structure and they make difficult to hanlde different data structure each time.

portnov commented 4 years ago

Yeah... 1) numba is good for "self-contained" code, when you have one function or several functions, that are called from each other, but never do "outside" calls. Unfortunately, there are not many such places in Sverchok. In fact, you have to write the code in this style, you can't just mark any random code with @jit and be happy. 2) python's nested lists, and lists in general, are not too effective. Numpy's multidimensional arrays are much more effective. There were... well.. impulses to rewrite the whole Sverchok to use numpy arrays instead of lists; but they never got too far.

alessandro-zomparelli commented 4 years ago

@portnov , I would love to help rewriting Sverchok, at least for a comparative test. It would be greatto use numpy + numba for example for the math node and other numerical operations. This would give a huge boost and much more stability to the data structure. Still, one of the other weakness is that it recompute the whole tree even with a small change in one part of it, but I don't know if this is a limitation of the Blender's Node System in general.

portnov commented 4 years ago

is that it recompute the whole tree

It's a weakness in Sverchok itself. There are some efforts to do not recalculate what obviously should not be, but these algorithms can be enhanced. There are even issues in progress about that - see #2380, #2439, #2393 ...

See also https://github.com/Sverchok/Sverchok — I believe this is the latest attempt to rewrite sverchok...

adalbert-homa commented 4 years ago

Animation nodes is using cython. See: https://animation-nodes-manual.readthedocs.io/en/latest/dev_guide/index.html

portnov commented 4 years ago

That requires developers (or, even worse, users) to build something, for each operating system supported. We do not want to do so: sverchok is installed by downloading zip file directly from github and pressing a button in preferences. We do not want to make this process any more complicated. Though, we can imagine some kind of "sverchok booster" addon, which would be built for specific platform, and then installed into Blender on top of sverchok.

Durman commented 4 years ago

https://devtalk.blender.org/t/suggestion-for-possible-improvements-in-the-performance-of-python-in-general/11596

kosirm commented 4 years ago

Tissue plugin (dev branch) is using Numba module and it is not complicated at all. For new users some simple tutorial can be done, I think. Just my 0.2 $

portnov commented 4 years ago

Yes, Numba has the advantage of not requiring compilation. But, as I mentioned before, it actually requires to write code in a specific way. So one can't just "add numba and be happy".

kosirm commented 4 years ago

This is beyond my domain :) Thanks for explanation!

zeffii commented 4 years ago

@portnov these are interesting things. this numba njit stuff.

zeffii commented 4 years ago

this was an interesting video : https://www.youtube.com/watch?v=x58W9A2lnQc

nortikin commented 4 years ago

i hope i have time for 'list zip', 'list flip', 'waffle', 'uvconnect' to rewrite, and with numpy/numba support. than i will just brutally cut or extend python lists for equal numpy.array. About waffle node it is more useful to have it as surface/curve or solid solution.

zeffii commented 4 years ago

okidoki :) on windows

python\bin> ./python.exe -m pip install numba
zeffii commented 4 years ago

i will need to find a way to make this work in SNlite node.. i don't dare assume it will work just-like-that :)

zeffii commented 4 years ago

oh wow. just the first call is slow.. as expected from the docs..

"""
in num_items s d=100 n=2
out dummy s
"""

from numba import jit
import numpy as np
import time

x = np.arange(num_items).reshape(10, 10)

@jit(nopython=True) # Set "nopython" mode for best performance, equivalent to @njit
def go_fast(a): # Function is compiled to machine code when called the first time
    trace = 0.0
    for i in range(a.shape[0]):   # Numba likes loops
        trace += np.tanh(a[i, i]) # Numba likes NumPy functions
    return a + trace              # Numba likes NumPy broadcasting

start = time.time()
print(go_fast(x))
end = time.time()
print("Elapsed (with compilation) = %s" % (end - start))  # Elapsed (with compilation) = 2.9859113693237305

start = time.time()
print(go_fast(x))
end = time.time()
print("Elapsed 2 (with compilation) = %s" % (end - start))  #  Elapsed 2 (with compilation) = 0.007998228073120117
zeffii commented 4 years ago

so it has an ahead-of-time compilation mode, which i think would need to be run by the individual-user's computer once before using. https://numba.pydata.org/numba-doc/latest/reference/aot-compilation.html#aot-compilation

zeffii commented 4 years ago

we have many functions that are heavy, not because the logic is heavy but because regular python has prohibitive overhead or numpy doesn't lend itself well because the algorithm isn't easily sanely expressed as a matrix multiplication/etc :)

zeffii commented 4 years ago

so @portnov i'm a total convert.

zeffii commented 4 years ago

slightly modified:

pacakge rd_test

reaction.py

# Turing Pattern Formation
# intro to modelling and analysis of complex systems
# https://math.libretexts.org/Bookshelves/Applied_Mathematics/Book%3A_Introduction_to_the_Modeling_and_Analysis_of_Complex_Systems_(Sayama)/13%3A_Continuous_Field_Models_I_-_Modeling/13.06%3A_Reaction-Diffusion_Systems

from numba import njit
import numpy as np

@njit
def reaction_test(steps, n=40, a=1.0, b=-1., c=2., d=-1.5, h=1., k=1.):
    # pylint: disable=c0103

    # n = 40  # size of grid n*n
    Dh = 1. / n  # spatial res, assuming space is [0, 1] * [0, 1]
    Dt = 0.02 # temporal res

    # a, b, c, d, h, k = 1., -1, 2., -1.5, 1., 1. # param values
    Du = 0.0001  # diffusion constant of U
    Dv = 0.0006  # dif  V

    u = np.zeros((n, n))
    v = np.zeros((n, n))
    for x in range(n):
        for y in range(n):
            u[x, y] = 1. + np.random.uniform(-0.03, 0.03)  # small noise is added
            v[x, y] = 1. + np.random.uniform(-0.03, 0.03)  # small noise is added
    nextu = np.zeros((n, n))
    nextv = np.zeros((n, n))

    for iteration in range(steps):
        for x in range(n):
            for y in range(n):
                # state-transition function
                uC, uR, uL, uU, uD = u[x, y], u[(x+1) % n, y], u[(x-1)%n, y], u[x, (y+1) % n], u[x, (y-1) % n]
                vC, vR, vL, vU, vD = v[x, y], v[(x+1) % n, y], v[(x-1)%n, y], v[x, (y+1) % n], v[x, (y-1) % n]

                uLap = (uR + uL + uU + uD - 4 * uC) / (Dh**2)
                vLap = (vR + vL + vU + vD - 4 * vC) / (Dh**2)
                nextu[x, y] = uC + (a*(uC-h) + b*(vC-k) + Du * uLap) * Dt
                nextv[x, y] = vC + (c*(uC-h) + d*(vC-k) + Dv * vLap) * Dt

        u, nextu = nextu, u
        v, nextv = nextv, v

    return u.ravel() > v.ravel()

snlite script

"""
in steps s d=100 n=2
in size s n=40 d=2
out nparray s
"""

from rd_test.reaction import reaction_test

uravel = reaction_test(steps, n=size)
nparray.append(uravel)

image

zeffii commented 4 years ago

also https://github.com/traveller59/second.pytorch/blob/master/second/core/geometry.py

portnov commented 4 years ago

Well, RD stuff looks nice, but I'm not sure where to apply it in Sverchok. Generate textures?

About geometry: I'll try to @jit some differential-geometry functions which appeared in sverchok lately (bezier curves, offset nodes, curvature calculations...). Will see if it is possible to refactor them so that they do not call non-jit-ed code. Not sure if it will do any good though. All these things are already use numpy (= written in C++ mostly).

zeffii commented 4 years ago

i'm rewriting inset_specials , or attempting.. it does require taking a few steps back.

i read however that nested functions are now supported in numba.jit , as long as those functions are not recursive. and don't themselves return a function.

zeffii commented 4 years ago

there are 2 major functions that i'm failing to implement a foolproof solution to, the one builds on the other.

where the criteria are expect the following input

in particular the ii.3 and iii.2 cases, maybe borrow from the scanline algorithm and mathutils.geometry.normal(vertlist) and rewrite the C code as python first. Remarkable lack of "out of the box" search results. lot's of proprietary solutions tho :)

@portnov any tips before i get entrenched down this rabbit hole ?

portnov commented 4 years ago

You can look at blender's source, how it calculates normals.

portnov commented 4 years ago

One of possible options is to find the "best fit" approximating plane for all vertices with least squares method and take it's normal (see sverchok.utils.geom.linear_approximation). But that may be too heavy.

zeffii commented 4 years ago

yeah, i'll distill the blender method (if it's the last thing i do)

my pride takes comfort in the fact that tessellation is sometimes someone's topic of BS thesis, a non trivial stuff.. is always hard to find clean examples of

zeffii commented 4 years ago

cool numba talk: https://www.youtube.com/watch?v=-4tD8kNHdXs (30+ minutes. really no-nonsense )