Monday, May 30, 2011

Initial backend work

We have started with the backend system. To recap, it will enable us to provide implementation backings for functions from various frameworks.

I've started with the Sobel operation, and implemented it in both opencv and opencl. At the same time I've reworked the numpy version as well so that identical results can be obtained. With different implementations at your disposable a great benefit is the way that you can test and benchmark different algorithms.

The working idea for now is to make a decorator that one can add to functions:

@add_backends
def sobel(image):
    # numpy implementation
    ...

This will add an optional backend implementation parameter to the function that the function will try to use:

# use the opencv sobel implementation
sobel(image, backend="opencv")
# use the opencl implementation on an available gpu
sobel(image, backend="opencl")

If the specified implementation is not found, we fall back to the default numpy backend. For global backend selections we are thinking of something in the following line:

use_backend("opencl")

This will try to use opencl wherever possible.

An alternative thought to our current setup is to specify it more explicitly:

opencv.sobel(image)

The following week we will try to finalize this API and implement a few more functions.

1 comment:

  1. As we discussed, I prefer mechanisms other than adding a keyword argument, as I think it makes switching between backends more difficult, and complicates debugging.

    I would rather have a system where I import a function from the scikit and it produces the version from the backend I have "use"d. For example:

    use_backend("opencl")
    from scikit.image.filters import sobel
    sobel.__module__

    This last line would produce 'scikit.image.filters.backends.opencl' (or something similar. If there were no sobel filter in the opencl backend, it would yield the default.

    I do like the idea of @add_backends pushing top-level documentation into the backend versions. In the example above, help(sobel) would produce the general documentation for the sobel() function, followed by anything specific to the opencl version.

    This also allows for more explicit imports of the backends directly. One thing it would lack (without more import hacking than we probably want) is producing a warning if a backend is used that does not have the requested function (defaulting back to numpy). However, this could still be done at runtime, with the @add_backends decorator. For functions not present in the backend, a warning-wrapped version of the numpy function could be placed in the backend module, so that this:

    from scikit.image.filter.backends.opencl import prewitt
    prewitt(im)

    produces a warning if prewitt is not present int he opencl backend.

    ReplyDelete