FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

reveal.js

reveal.js

Going native: C++ as a first-class citizen of the Jupyter ecosystem

The team

Project Jupyter

  • Consistent set of tools to improve and unify scientific computing workflows,
  • An interface between metal and humans, metal and flesh.

From day 1, Jupyter was developed by scientists for scientists and educators

Interactive workflows

Programming languages are not only used to build complex systems, but also to explore and gain insight about

  • A computing resource
  • A data set
  • The outcome of a simulation

Interactive workflows:

  • Loading some data
  • Running some code
  • Showing a visualization
  • Running some more code...

The C++ programming language

  • Taylored for performances
  • With a massive community
  • Especially in HPC

(Outside of ROOT) We lack a good story for interative computing in C++

This hurts productivity of C++ software developers.

  • C++ is generally considered as a difficult programming language
  • Heterogeneous set of tools...
  • ... that don't always play well together
  • making scientific workflows hard to reproduce

A C++ kernel for Jupyter based on

  • A modern C++ implementation of the Jupyter protocol

  • Cling, the C++ interpreter developed at CERN

Live demo of Xeus-Cling

Jupyter interactive widgets

Another area where Jupyter shines is Jupyter interactive widgets

Jupyter interactive widgets: thick front-end and thin back-end

  • A modern C++ back-end for Jupyter interactive widgets
  • Uses the front-end implementation of ipywidgets

Live demo of xwidgets

Next goal: implement C++ back-end for other widgets libraries

  • bqplot
  • ipyleaflet
  • pythreejs
  • ipyvolume
  • ...
  • A modern C++ back-end for ipyleaflet
  • Uses the front-end implementation of ipyleaflet

Live demo of xleaflet

Voila

The Lazy Tensor Algebra Expression System

Xtensor is a flexible expression system in which any data structure can be plugged, offering the most expressive API to the users.

What is xtensor?

  • A C++ template library for multi-dimensional array manipulation

    • Followings the idioms of the C++ STL

      (iterator pairs, clear value semantics)

    • But also an API similar to that of numpy

What is xtensor?

  • Python bindings to enable xtensor APIs on numpy arrays.

  • Julia bindings to enable xtensor APIs on Julia arrays.

  • R bindings to enable xtensor APIs on R arrays.

  • Cookiecutter projects for authoring of Python, Julia, and R extensions.

What is xtensor?

  • BLAS bindings to enable BLAS operations on xtensor expressions.

  • SIMD acceleration kernels.

  • All open-source (BSD License).

Ever heard of numpy ?

Python 3 - numpy

C++ 14 - xtensor

                                    np.array([[3, 4], [5, 6]])

                                    arr.reshape([3, 4])
                                
                                    xt::xarray<double>({{3, 4}, {5, 6}})
                                    xt::xtensor<double, 2>({{3, 4}, {5, 6}})
                                    arr.reshape({3, 4});
                                
                                    np.linspace(1.0, 10.0, 100)
                                    np.logspace(1.0, 10.0, 100)
                                    np.arange(3, 7)
                                    np.eye(4)
                                    np.zeros([3, 4])
                                    np.ones([3, 4])
                                
                                    xt::linspace<double>(1.0, 10.0, 100)
                                    xt::logspace<double>(1.0, 10.0, 100)
                                    xt::arange(3, 7)
                                    xt::eye(4)
                                    xt::zeros<double>({3, 4})
                                    xt::ones<double>({3, 4})
                                

Python 3 - numpy

C++ 14 - xtensor

                                    a[:, np.newaxis]
                                    a[:5, 1:]
                                    a[5:1:-1, :]
                                    np.broadcast(a, [4, 5, 7])
                                    np.vectorize(f)
                                    a[a > 5]
                                    a[[0, 1], [0, 0]]
                                
                                    xt::view(a, xt::all(), xt::newaxis())
                                    xt::view(a, xt::range(_, 5), xt::range(1, _))
                                    xt::view(a, xt::range(5, 1, -1), xt::all())
                                    xt::broadcast(a, {4, 5, 7})
                                    xt::vectorize(f)
                                    xt::filter(a, a > 5)
                                    xt::index_view(a, {{0, 0}, {1, 0}})
                                
                                    np.sum(a, axis=[0, 1])
                                    np.sum(a)
                                    np.prod(a, axis=1)
                                    np.prod(a)
                                    np.mean(a, axis=1)
                                    np.mean(a)
                                
                                    xt::sum(a, {0, 1})
                                    xt::sum(a)
                                    xt::prod(a, {1})
                                    xt::prod(a)
                                    xt::mean(a, {1})
                                    xt::mean(a)
                                

Python 3 - numpy

C++ 14 - xtensor

                                    np.where(a > 5, a, b)
                                    np.where(a > 5)
                                    np.any(a)
                                    np.all(a)
                                    np.logical_and(a, b)
                                    np.logical_or(a, b)
                                
                                    xt::where(a > 5, a, b)
                                    xt::where(a > 5)
                                    xt::any(a)
                                    xt::all(a)
                                    a && b
                                    a || b
                                
                                    np.absolute(a)
                                    np.exp(a)
                                    np.sqrt(a)
                                    np.cos(a)
                                    np.cosh(a)
                                    scipy.special.erf(a)
                                    np.isnan(a)
                                
                                    xt::abs(a)
                                    xt::exp(a)
                                    xt::sqrt(a)
                                    xt::cos(a)
                                    xt::cosh(a)
                                    xt::erf(a)
                                    xt::isnan(a)
                                

Python 3 - numpy

C++ 14 - xtensor

                                    np.random.seed(0)
                                    np.random.randn(10, 10)
                                    np.random.randint(10, 10)
                                    np.random.rand(3, 4)
                                
                                    xt::random::seed(0)
                                    xt::random::randn<double>({10, 10})
                                    xt::random::randint<int>({10, 10}})
                                    xt::random::rand<double>({3, 4}})
                                
                                    np.stack([a, b, c], axis=1)
                                    np.concatenate([a, b, c], axis=1)
                                
                                    xt::stack(xtuple(a, b, c), 1)
                                    xt::concatenate(xtuple(a, b, c), 1)
                                

Broadcasting

                                    xarray<int> a = {{1,  2,  3,  4},
                                                     {5,  6,  7,  8},
                                                     {9, 10, 11, 12}};
                                    xarray<int> b = { 1, 3, 5, 7};
                                
                                    xarray<int> res = a + b;
                                

Broadcasting

                                    xarray<double> a = {1., 2., 3., 4.};
                                
                                    auto res = xt::broadcast(a, {3, 4});
                                
                                    xarray<double> a, b, c;
                                    // ... initialization of a, b, and c ...
                                    auto res = broadcast(a + b * c, {3, 4});
                                

Iteration

Row-major iteration over the array for x in np.nditer(a)
                                for(auto it=a.begin(); it!=a.end(); ++it)
                                
Iterating over a with a prescribed broadcasting shape
                                a.begin({3, 4})
                                a.end({3, 4})
                                
Iterating over a in a column-major fashion
                                a.template begin<layout_type::column_major>()
                                a.template end<layout_type::column_major>()
                                
Iterating over a in a column-major fashion with a prescribed broadcasting shape
                                a.template begin<layout_type::column_major>({3, 4})
                                a.template end<layout_type::column_major>({3, 4})
                                

How do I try it without installing anything?

http://quantstack.net/xtensor

Live demo

Language bindings with xtensor

A Simple Python extension (1/2)

C++: Using an algorithm from the STL on a numpy array


#include <numeric>                        // Standard library import for std::accumulate
#include "pybind11/pybind11.h"            // Pybind11 import to define Python bindings
#include "xtensor/xmath.hpp"              // xtensor import for the C++ universal functions
#define FORCE_IMPORT_ARRAY                // numpy C api loading
#include "xtensor-python/pyarray.hpp"     // Numpy bindings

double sum_of_sines(xt::pyarray<double>& m)
{
    auto sines = xt::sin(m);
    // sines does not actually hold any value, which are only computed upon access
    return std::accumulate(sines.begin(), sines.end(), 0.0);
}

PYBIND11_PLUGIN(xtensor_python_test)
{
    xt::import_numpy();
    pybind11::module m("xtensor_python_test", "Test module for xtensor python bindings");

    m.def("sum_of_sines", sum_of_sines,
        "Computes the sum of the sines of the values of the input array");

    return m.ptr();
}

A simple Python extension (1/2)

Python: Using an algorithm from the STL on a numpy array


import numpy as np
import xtensor_python_test as xt

a = np.arange(15).reshape(3, 5)
xt.sum_of_sines(v)

A simple Python extension (2/2)

C++: Create a universal function from a C++ scalar function


#include "pybind11/pybind11.h"
#define FORCE_IMPORT_ARRAY
#include "xtensor-python/pyvectorize.hpp"
#include <numeric>
#include <cmath>

namespace py = pybind11;

double scalar_func(double i, double j)
{
    return std::sin(i) - std::cos(j);
}

PYBIND11_PLUGIN(xtensor_python_test)
{
    xt::import_numpy();
    py::module m("xtensor_python_test", "Test module for xtensor python bindings");

    m.def("vectorized_func", xt::pyvectorize(scalar_func), "");

    return m.ptr();
}

A simple Python extension (2/2)

Python: Create a numpy-style universal function from a C++ scalar function


import numpy as np
import xtensor_python_test as xt

x = np.arange(15).reshape(3, 5)
y = [1, 2, 3, 4, 5]
xt.vectorized_func(x, y)

A Simple Julia extension (1/2)

C++: Using an algorithm from the STL on a Julia array


#include <numeric>                        // Standard library import for std::accumulate
#include "jlcxx/jlcxx.hpp¨                // CxxWrap import to define Julia bindings
#include "xtensor-julia/jltensor.hpp"     // Import the jltensor container definition
#include "xtensor/xmath.hpp"              // xtensor import for the C++ universal functions

double sum_of_sines(xt::jltensor<double, 2> m)
{
    auto sines = xt::sin(m);  // sines does not actually hold values.
    return std::accumulate(sines.cbegin(), sines.cend(), 0.0);
}

JULIA_CPP_MODULE_BEGIN(registry)
    jlcxx::Module mod = registry.create_module("xtensor_julia_test");
    mod.method("sum_of_sines", sum_of_sines);
JULIA_CPP_MODULE_END

A simple Julia extension (1/2)

Julia: Using an algorithm from the STL on a Julia array


using xtensor_julia_test

arr = [[1.0 2.0]
       [3.0 4.0]]

sum_of_sines(arr)

A simple Julia extension (2/2)

C++: Create a numpy-style universal function from a C++ scalar function


#include "jlcxx/jlcxx.hpp"
#include "xtensor-julia/jlvectorize.hpp"

double scalar_func(double i, double j)
{
    return std::sin(i) - std::cos(j);
}

JULIA_CPP_MODULE_BEGIN(registry)
    jlcxx::Module mod = registry.create_module("xtensor_julia_test");
    mod.method("vectorized_func", xt::jlvectorize(scalar_func));
JULIA_CPP_MODULE_END

A simple Julia extension (2/2)

Julia: Create a numpy-style universal function from a C++ scalar function


using xtensor_julia_test

x = [[ 0.0  1.0  2.0  3.0  4.0]
     [ 5.0  6.0  7.0  8.0  9.0]
     [10.0 11.0 12.0 13.0 14.0]]
y = [1.0, 2.0, 3.0, 4.0, 5.0]
xt.vectorized_func(x, y)

A Simple R extension

C++: Using an algorithm from the STL on a R array


// [[Rcpp::export]]
double sum_of_sines(xt::rarray<int> m)
{
    auto sines = xt::sin(m);  // sines does not actually hold values.
    return std::accumulate(sines.cbegin(), sines.cend(), 0.0);
}

A simple R extension

R: Using an algorithm from the STL on a R array


library('xtensor_r_test')

arr <- array(c(c(1, 2), c(3, 4)), dim = c(2, 2)

xtensor_r_test::sum_of_sines(arr)

Generate your packaged xtensor extension

  • With a few examples from the documentation
  • Unit-tests
  • HTML documentation
  • Packaging boilerplate (setup.py, build.jl)

Bindings with BLAS libraries

BLAS-based implementation of numpy.linalg

  • ISO results with numpy.linalg is main goal
  • Seeking adoption by Python to C++ compilers (Pythran, Jet)
  • Works with any BLAS implementation (openblas, mkl, netlib)
  • See the numpy to xtensor cheat sheet

Continually benchmarking

We benchmark.
A lot!

  • C++ dataframe library
  • Based on xtensor
  • Currently in an alpha stage

Live demo of xframe

Resources:

GitHub

  • xeus: github.com/QuantStack/xeus/
  • xeus-cling: github.com/QuantStack/xeus-cling/
  • xproperty: github.com/QuantStack/xproperty/
  • xframe: github.com/QuantStack/xframe/
  • xtensor: github.com/QuantStack/xtensor/
  • xtensor-blas: github.com/QuantStack/xtensor-blas/
  • xtensor-python: github.com/QuantStack/xtensor-python/
  • xtensor-r: github.com/QuantStack/xtensor-r/
  • xtensor-julia: github.com/QuantStack/xtensor-julia/
  • xsimd: github.com/QuantStack/xsimd/
  • xtensor-fftw: github.com/egpbos/xtensor-fftw/
  • xwidgets: github.com/QuantStack/xwidgets/
  • xleaflet: github.com/QuantStack/xleaflet/
  • xplot: github.com/QuantStack/xplot/
  • xwebrtc: github.com/QuantStack/xwebrtc/

Resources:

Documentation

  • xeus.readthedocs.io
  • xproperty.readthedocs
  • xtensor.readthedocs.io
  • xtensor-python.readthedocs.io
  • xtensor-julia.readthedocs.io
  • xtensor-r.readthedocs.io
  • xsimd.readthedocs.io
  • xplot.readthedocs.io
  • xleaflet.readthedocs.io

The End


Back | FazBrowse Home | New Git URL