Ivy is useful tool for any developer wishing to maximize the audience of their codebase, by making their code framework-agnostic.
First, we explain how to write framework-agnostic Ivy code. We then explain the variety of ways in which an end user can run your Ivy code, using their specific choice of backend framework.
Writing Ivy code is simple.
ivy namespace provides access to all of the Ivy functions,
which can all be used directly with tensors from any of the supported deep learning frameworks.
Let’s assume the codebase that you wish to share with the community consists of a single simple function, outlined below. In reality, your code will likely be a little more complex than this!
import ivy def sincos(x): return ivy.sin(ivy.cos(x))
That’s it, having used the Ivy namespace to write your code, it is now framework-agnostic! There is nothing more to it!
When it comes to an end user actually running your code alongside their specific framework, there are a number of options.
Firstly, the user can simply use your new function directly in their code, like so:
import tensorflow as tf from your_awesome_project import sincos # some exciting tf code x = tf.constant([1.]) y = sincos(x) # with type checking # more exciting tf code
In this simple format, each
ivy method will simply type-check the inputs to infer the correct backend framework,
and then call the framework-specific functions. A PyTorch user’s code would look like this:
import torch from your_awesome_project import sincos # some exciting torch code x = torch.tensor([1.]) y = sincos(x) # with type checking # more exciting torch code
This is the simplest way for an end user to run your framework-agnostic code. However, in eager execution mode the continual type-checking adds a small overhead, which we may wish to avoid.
To avoid the small type-checking overhead, the framework can be set explicitly, by calling
ivy.set_framework("torch") for example.
This updates the
__dict__ of the
ivy namespace with the
__dict__ of a framework-specific namespace,
ivy.torch. The framework-specific namespace bypasses type-checking of the inputs.
The end user would use your codebase like so:
import ivy import torch from your_awesome_project import sincos ivy.set_framework('torch') # some exciting torch code x = torch.tensor([0.]) y = sincos(x) # no type checking # more exciting torch code ivy.unset_framework()
Framework Block Setting
Finally, some users may wish to use multiple frameworks in a single project. For example, NumPy is often used in conjunction with DL frameworks. NumPy can be used for implementing non-differentiable parts of the project on the CPU, and interfacing with other packages such as OpenCV and MatPlotLib for visualization.
For end users wishing to use different parts of their code with different backends in a single project,
without using repeated calls to
with statement can be used like so:
import ivy import torch import numpy as np from your_awesome_project import sincos with ivy.numpy.use: # some exciting np code x = np.array([0.]) y = sincos(x) # no type checking # more exciting np code with ivy.torch.use: # some exciting torch code x = torch.tensor([0.]) y = sincos(x) # no type checking # more exciting torch code
Overall, this variety in backend selection gives end users a lot of flexibility.
If they want to dive straight into using your Ivy project, then they can start using functions immediately,
with type-checking in the background. If they use only a single backend in their project,
they can explicitly set this at the beginning of their own code using
Finally, if they use multiple backends in one project,
they can set and unset the frameworks using either
or via the