diff --git a/HISTORY.rst b/HISTORY.rst
index 143998c49..42f0e2b5b 100644
--- a/HISTORY.rst
+++ b/HISTORY.rst
@@ -5,16 +5,18 @@
History
=======
-current - 2020-02-15 - 0.00Mb
+current - 2020-02-19 - 0.00Mb
=============================
+* `93`: Use pointer for TreeClassifier (2020-02-19)
+* `99`: Fixes #93, use same code for TreeEnsembleClassifier and TreeEnsembleRegression (2020-02-19)
* `98`: mlprodict i broken after onnxruntime, skl2onnx update (2020-02-15)
* `97`: Add runtime for operator Conv (2020-01-24)
* `96`: Fixes #97, add runtime for operator Conv (2020-01-24)
* `95`: Fix OnnxInference where an output and an operator share the same name (2020-01-15)
* `94`: Raw scores are always positive for TreeEnsembleClassifier (binary) (2020-01-13)
-* `86`: Use pointers to replace treeindex in tree ensemble cpp runtime (2019-12-17)
* `90`: Implements a C++ runtime for topk (2019-12-17)
+* `86`: Use pointers to replace treeindex in tree ensemble cpp runtime (2019-12-17)
* `92`: Implements a C++ version of ArrayFeatureExtractor (2019-12-14)
* `89`: Implements a function which extracts some informations on the models (2019-12-14)
* `88`: Fix bug in runtime of GatherElements (2019-12-14)
diff --git a/_doc/notebooks/onnx_tree_ensemble_parallel.ipynb b/_doc/notebooks/onnx_tree_ensemble_parallel.ipynb
new file mode 100644
index 000000000..55f68e29e
--- /dev/null
+++ b/_doc/notebooks/onnx_tree_ensemble_parallel.ipynb
@@ -0,0 +1,918 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# TreeEnsembleRegressor and parallelisation\n",
+ "\n",
+ "The operator [TreeEnsembleRegressor](https://github.com/onnx/onnx/blob/master/docs/Operators-ml.md#ai.onnx.ml.TreeEnsembleRegressor) describe any tree model (decision tree, random forest, gradient boosting). The runtime is usually implements in C/C++ and uses parallelisation. The notebook studies the impact of the parallelisation."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "
run previous cell, wait for 2 seconds
\n",
+ ""
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "execution_count": 2,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "from jyquickhelper import add_notebook_menu\n",
+ "add_notebook_menu()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%matplotlib inline"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Graph\n",
+ "\n",
+ "The following graph shows the time ratio between two runtimes depending on the number of observations in a batch (N) and the number of trees in the forest."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {
+ "scrolled": false
+ },
+ "outputs": [
+ {
+ "data": {
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAAAaUAAAEYCAYAAAD8hukFAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjEsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy8QZhcZAAAf4klEQVR4nO3de5zVdb3v8deHiwgOdy8Ro4IwppxUMoLMMLqoYCRi6Ak5oYYRbk3Tx9k73UejwdrV3pllXmhKQI873JzcCSgKytl42yWXQtKQwNmYgwohA8NwEZDP/uO7xllzZa2ZdfnOWu/n4zGPWb/v+l2+P37DvOd7Wb+fuTsiIiIx6JTvCoiIiNRRKImISDQUSiIiEg2FkoiIREOhJCIi0VAoiYhINBRKIiISDYWSiIhEQ6EkIiIAmNnpZjbbzH5jZtfmow4KJRGRAmZmc8xsm5m90qh8rJltMLNNZnYLgLuvd/cZwOXAiHzUV6EkIlLY5gFjkwvMrDNwLzAOGAZMNrNhifcuBl4Alue2mkGXfBxURESaGmvm29NYfw28CuxPKqpw94rkddz9OTMb1GjTkcAmd68EMLNHgAnAn919EbDIzJ4Afp3mKbSbQklEJBLbgdVprG+w393b0s02EHgzabkKGGVmY4BLgW7Akjbst90USiIiMemUxqjK4cNtPYo1U+buvgJY0dadZoLGlEQk48xslJmNzHc9OqROnVL/gt5mVmFmX0rzKFXAiUnLpcBbmTqF9lAoiUhGmVkX4LPAQjP7uZnp90yqzNINpV3uPt3dF6d5pFVAmZkNNrOjgK8AizJ9Om2hHxYRySh3P+TuPyT8kuvm7m3uYypK6YXSEZnZfOB3wEfMrMrMprn7IeB6YCmwHljg7q9m7ZzSYHryrIhkmpl9BrgbuMDdt5rZ8cC5hHGLx/Jbu3iN6NzZVx99dMrr2969m4D/ABa3obUUJU10kIJmZqMIvwhX5rsuxcLMugI3A48kAmlkYrkWGGZmVwBXu/uefNYzWulMdEh032WrKvmg7jspWBrbyJsrgOPd/QeJ5V8Av3P3a4DPAYfQH8Qty3D3XUdTmGclgsY2csnMupjZFWZWAkwFfpIovwHo7O4/S9xFwIFewMmJ9web2YX5qnd00p/oUHAK86wipWmyuZcY2/gkcHti+Xgzm2hml+S3ZgWnBzAJeBv4sLv/v0T53wE3ALj7+8BkoK+7rzOzrwL3Azcn7sE2LA/1jk9upoRHS6GUI+pKyr0WxjbuBr4I/IOZLTCzY8ysuQ8SShrcvcbdLwUuA7qa2U2JuwOsBV5MWvX7wLfMbDLwKeAed78QeBA4I8fVjk/upoRHS78Yc6RRV9JR6krKiSONbRwkdC1pCmqGuPtT7j4UeBz4I6EF1TcR/j8l3C3gVeAq4DfA/09sejJ5uit1dIq8+06DjTmU1JX0hcRyJ4VTZiVapJcTwv9IYxs9gaHAH/JU3YLl7hsT/86VwPPAOmArcB0hkFYDa919b+JmoR8HpoD+XxRq2KRKoZQjSV1JD7v734r+P1721I1t/AKoajS2MQPC2EZiWnKpuyuQsiQxhvQtM/sF0B1Y5+6HzOxYYAtQk1j1BmAZ8EZiu+L9f1HXfZe63mZWgT6nJG1wBXCcu/9LYlldRlng7jXApWY2FrjHzG4idCM1Htv4J+AboL/Ms83d1zcq6gNsdfeDiWf3nAN8zd33N926CBX555QUSlnUTFfSvyTKOyf+ipQscfengKFmVgZso35sYw9QTug6WmJmpkDKuReAO83sHKAM+FkzwVWc0m8pFRyFUnYldyW96e6/hQ+6NSQHWhnbKKi/LjsSd/93M/sdMAb4rrtvzm+NIlPkoaR73+VAXVcSMBu419335blKRcnMTieMbax198OJVpL+A0g0RnTr5qtLS1Ne3yor17TxIX/RUkspB5K6kj6iQMqfxl1ECiSJjiY6KJRyyd035LsOIhI5TXQQEZEoaKKDQklEJCoKJRERiYIZdCnuX8vFffYiIrEp8pZScZ99DplZQQ1GdmS6FvHQtWgk/buE69EV0mb6zxcPXYt46Fo0VuSPrlD3nYhITIq8+66jhFKH/5Bj4nOaHf48CoGuRTwK4lrMnAnl5Zl5UKSmhHeYUBIRKQ4KpY5DD63Or+Sb8sycmb96FLvy8qQFXYj8anAxMkAtpY4VSiIiBU+hJCIi0SjyUCrusxcRiYk+p6SWkohIVHSXcBERiYImOiiURESiolASEZFoKJRERCQK6r5TKImIREWhJCIiUVBLSaEkIhIVhZKIiERBLSWFkohIVIo8lIr77EVEYqPbDImISBTS777TbYZERCSLirz7TqEkIhILTXRQKImIREWhJCIi0VAoiYhIFNR9p1ASEYmKQklERKKglpJCSUQkKgolERGJhkJJRESioO47hZKISFQUSiIiEgW1lBRKIiJRUSiJiEg0FEoiIhKFPHffmdklwBeB44F73X1ZrutQ3JEsIhKb9B7yd0RmNsfMtpnZK43Kx5rZBjPbZGa3ALj7Y+7+deAq4H9m+tRSoVASEYlFXUspg6EEzAPGNjyMdQbuBcYBw4DJZjYsaZXbEu/nnEJJRCQm6YXSsWa2OumryVNo3f05YEej4pHAJnevdPcDwCPABAt+BDzp7n/I9qk2R2NKIiIxSW9Mabu7j2jDUQYCbyYtVwGjgG8CXwB6m9lQd5/dhn23i0JJRCQWuZvoYM2UubvfDdydiwq0RN13IiIxSa/7rreZVZjZl9I8ShVwYtJyKfBWpk6hPdRSEhGJRfotpV3u3mQcKQWrgDIzGwxsAb4CXNGG/WScWkoiIjHJ/JTw+cDvgI+YWZWZTXP3Q8D1wFJgPbDA3V/N2jmlQS0lEZGYZHhMyd0nt1C+BFiS0YNlgFpKIiKxSP9zSm0dU4qWWkoiIjHJzZhStBRKIiKx0KMrFEpt9xRwI/A+cA1wS6P3nwO+BawjfFh6UtJ7DwLfS7y+DbgyqzUtZIsWfY2//OVxjjnmeK699pUm77s7S5feyMaNS+jatQcTJsxjwICzAXj55Qd5/vlwHUaPvo2zztJ1SMmECXDqqbBnD9x3Xyjr3h0uuwz69IGdO2HBAti/P7w3bhyUlcHBg/DYY/D22033OWAATJwIXbrAxo3w5JNH3m+hSi+UeptZBbDY3RdnqUY5lZdIbukGgR3H+8B1wJPAn4H5ie/JTiLccqrxLMsdQDnwErAy8bo6i3UtbGeddRVTpjzV4vubNj3Ju+9u5PrrNzJ+fAVPPHEtAPv27eDZZ8uZNu0lpk1bybPPlrNvn65DStauhYcfblj26U9DZSXcfXf4Pnp0KC8rg/79Q/nixTB+fPP7HD8eFi0K6/XvD0OHtr7fQpbemNIud59eKIEE+ZvoMI9GNwjsWFYCQ4FTgKMIU/wXNlpnEHAmTf+JlwLnA/2AvonXTwFvAGXAduAwMBrI+V3jO5yTTz6P7t37tfj+hg0LOeusqZgZpaWf5L33drJ799u8/vpSTjnlfLp370f37n055ZTzef31p9i58w3uuaeMvXu3436YuXNH8/rrug4NvPEG7NvXsOy000JYQfh+2mlNy6uq4OijoaSk4bYlJdCtW3i/bvvTT299v+PGwWc+E14PGQJXXx26vjq67NyQtUPJS/eduz9nZoPycezM2ELTD0O/1I5ttwAnA98GZhBuQTUMuKDdNS12u3dvoVev+n/vnj1L2b17CzU1Dct79SqlpmYLffqczKc+9W2eeGIGAweO4rjjhjFkiK7DER1zDNTWhte1tWEZoGdPqKmpX6+mBnr1ql8XwnLjdXr2bH2/zzwD06eHgLzootByc8/OueVagYZNqqI9ezObXnfn24qKinxXp5HmfvhT/SuttW2vAXYDs4Eft6Fe0pg3+4vKaO46WOIv7bPPvob33tvNmjWzOf98XYd2aa71konwOHgwdPdNnQorV0J1gXS9akp4vBMd3L0CqEujyP4EKqXpDXY/nMa2KxptOybxem9iGaAW6NnmGkoQWkD112r37ip69vwwvXqVsnnzig/Ka2qqGDRoDAAHD+5l9+5wHQ4cqKVbN12HI9qzJ3TD1daG73v2hPK6llGdXr1g9+6G27a2Tkv7BTjhhNCN2LPArk+RTwmPtqUUt08AG4H/AuoeRXJxitteSBgrqk58LUuUQei+mwLMAr6ewfoWr1NPvZiXX34Id6eq6vd069abnj0HMGTIhVRWLmPfvmr27aumsnIZQ4aE6/DMM9/mox+dwpgxs3j8cV2HlGzYAMOHh9fDh8Nrr4XXr71WX15aGmbOJXfdQVg+cCC833j7lvbbuzeccw7Mnh0mRQwcmL1zyzWNKUn6ugD3EMLkfeBrwP8AvgOMIATUKmAiIXgWAzOBVwkTHG4nBBuJbfoBzya2eRHoDDwKzAWuzsUJdViPPjqZN95Ywd6927nrrlLGjCnn/fcPAjBixAzKyi5i06Yl3HPPULp27cHFF88FoHv3fowefTu/+lW4Dued9x26d+/H5s3P8tZbq7j66hfp1Kkz69c/ytq1cxk+XNfhA5MmwaBB0KMH3HwzrFgBzz8Pl18OZ58Nu3aFqdsQpnefeirceGP9lPA6M2aEUAF4/HG45BLo2jVss3FjKG9pvxMmwLJloUW1cGGYTl5RAYcO5epfITv0OSWs+T73LB803CBwDHAssBWY6e4PtLKJh+2yXzdpWfKPysyZ+atHsSsvT1rQhciv8vJwDcrLM/LbacTgwb561qyU17epU9e08SF/0crX7LtmbxAoIlLU0m8pFdyHZ9V9JyISkyKf6KBQEhGJhcaUFEoiIlFRKImISDQUSiIiEgV13ymURESiUuShVNxnLyISE937Ti0lEZGoaEq4iIhEo8i77xRKIiKx0EQHhZKISFQUSiIiEgW1lBRKIiJRKfJQKu6zFxGJjaaEi4hIFMygS1q/ljUlXEREskRjSgolEZGoKJRERCQaCiUREYmCuu8USiIiUVEoiYhIFNRSUiiJiERFoSQiItFQKImISBTUfadQEhGJSpGHUnGfvYhITPQ4dLWURESiosehi4hINIq8+06hJCISC010UCiJiERFoSQiIlFQS0mhJCISFYWSiIhEQ6EkIiJRUPfdkT88a2b/bGa9zKyrmS03s+1m9r9yUTkRkaKT3odno2ZmJzf31do2qbSULnD3fzCziUAVcBnwH8DDGaiziIjUKbyW0mLAAAeOAU4G/gIMa2mDVEKpa+L7RcB8d99hZu2sp4iINKuAQsndz0xeNrNPAFe1tk0qZ7/YzF4DRgDLzew4YH9bKykiIi1I/9530TOzM81sEIC7rwI+2dr6R2wpufstZvYjoMbd3zezvcCEDNRVREQa6yBhkwozmwsMB0rM7E7gEWCtmZm7e3PbpDLRoQdwHXB/oujDhFaTiIhkWmG1lEYCZwMfB77u7juBM1sKJEit+24ucAD4VGK5CvheOysqIiKN5bn7zsxOMbMHzOw3GdplJXC8u9cAXcysE3B0axukclZD3P2fgYMA7r6PMJtCREQyLcOhZGZzzGybmb3SqHysmW0ws01mdguAu1e6+7QMns17wMuJbrwPAcuBVgMvldl3B8ysO2FKH2Y2JHEgERHJpOxMCZ8H3AM8VH8Y6wzcC5xP6P1aZWaL3P3PGT72osQXwJPAn939lVbWx1rp2gsrmJ0P3EaYV74MOBe4yt1XtLe2aWi9kiIi+WIG7hnpPRoxYoSvXrUq9UN36rTG3Y84xp+Y/fa4u380sXwO8F13vzCxfCuAu/8gsfwbd5+U9gmkUmezb7r7z1t6/4iR7O5PA5cS5pbPB0bkOJBERIqGYyl/Acea2eqkr1SfQjsQeDNpuQoYaGb9zWw28LG6oGoPM7vezF42s/9KfFUCP068vrG5bY7YfWfhk7LjgFPcfZaZnWRmI919ZXsrLCIiDR0+nNbq21NpKTWjuZadu/u7wIw27K8l1xHyo6buGMAK4LPA3uY2SGVM6T7gMPA5YBawG3gU+ET76pq++fNzfURJNnly0sLMmXmrR9ErL69/rbur5NcRhj/asrs0Q6m3mVUAi919cRrbVQEnJi2XAm+ldeTUvOXum5MLzGy7u+9oaYNUQmmUu59tZn8EcPdqMzuqffUUEZHmpBlKu9w91S67ZKuAMjMbDGwBvgJc0Yb9tMrdP59KWbJUQulgYqZG3ey74wgtJxERyaA2tJSOyMzmA2MI409VwEx3f8DMrgeWAp2BOe7+amaPDIkxpLobsn5Q7O6Dzexxdx/feJtUQulu4LfA8Wb2fWASYTaeiIhkWKZDyd0nt1C+BFiS2aM10dp4V7Mts1TuffevZrYG+Dwh8S5x9/Vtq5+IiLQmR2NKOZF4qsTHgPMIraUX3P0Pifdqmtum1VBK3BJiXWJu+2sZrq+IiCRpQ/ddW8eUcsLMvkX4ONFjiaK5Zvagu/+kpW1aDSV3P5yYY36Su/81c1UVEZHmZLr7Ls+mAZ9w9/0AZvZDwiSLtoVSwgDgVTNbCeypK3T3i9tXVxERSZbDKeG54oSJFHU+mDTXklRCqQRIniFhwI/SrpqIiBxRIXXfAb8Efm9mv00sX5ooa1EqodTF3Z9NLkjcoFVERDIoG1PC88ndf25mzwGjE0VT3P3l1rZpMZTM7Frg74BTzGxd0ls9gRfbW1kREWmqkEIJIBFCrQZRstZaSr8m3Gr8B8AtSeW7W7tFhIiItF2hhVK6Wgwld98F7AKa/eCViIhkVgFOdEhbKmNKIiKSIwU20SFtCiURkUgU2kSHtlAoiYhERKEkIiLRKPZQOuLj0EVEJDfquu9S/SIx0cHMvpTnqmeMWkoiIhHRRAcREYmCJjoolEREoqJQEhGRaCiUREQkCuq+0+w7EZGoaPadiIhEodAeh94WCiURkYgUe/edQklEJCIKJRERiYImOiiURESiolASEZEoqKWkUBIRiUqxh5I+pyQiEhF9TklERKKgzykplEREolLs3XcKJRGRSGiig0JJRCQqCiUREYmGQklERKKg7juFkohIVBRKIiISBbWUFEoiIlFRKImISDSKPZR0myERkUjUdd/pNkOSlnfffZP775/Kzp3vYNaJz31uOuPG3dhgHXfnoYduZO3aJRx1VA9mzJjH4MFnA/Dccw/y299+D4CJE2/jvPOuzPk5dDgTJsCpp8KePXDffaGse3e47DLo0wd27oQFC2D//vDeuHFQVgYHD8Jjj8Hbbzfd54ABMHEidOkCGzfCk08eeb/F6oEHYPx42LYNzjgjlPXtC//2bzBoEGzeDJdfHv69AH72M7joIti7F666Cv74x1A+dSrcdlt4/b3vwUMPNT1WW/ZbINzh0KG0Nim42wxlraVkZnPMbJuZvZJU1s/MnjazjYnvfbN1/Gzq1KkLU6bcyY9/vJ5Zs37P00/fS1XVnxuss3btk7zzzkZ+8pONXHNNBXPmXAtAbe0OHn20nDvueIk77ljJo4+WU1tbnY/T6FjWroWHH25Y9ulPQ2Ul3H13+D56dCgvK4P+/UP54sXhl2lzxo+HRYvCev37w9Chre+3mM2bB2PHNiy75RZYvjz8sbB8eViG+j8Iyspg+nS4//5Q3rcvzJwJo0bByJHhdZ8+TY+V7n4LTJotpYKTze67eUCjn2JuAZa7exmwPLHc4fTtO+CDVk/37j0ZOPB0qqu3NFhnzZqFjB49FTOjrOyT7N27k+rqt1m3bilnnHE+JSX9KCnpyxlnnM+6dU/xt7+9wU03lVFTs53Dhw9TXj6adeuW5eP04vTGG7BvX8Oy004LYQXh+2mnNS2vqoKjj4aSkobblpRAt27h/brtTz+99f2OGwef+Ux4PWQIXH01mGXuHGP2/POwY0fDsgkT4MEHw+sHH4RLLqkvr2sBvfRSCJ4PfQguvBCefhqqq0PL5+mnmwZdW/Z7ySVhXxCWN2yAE07I3LnnUBu67wpO1kLJ3Z8DGv0UMwFI/LTxIHBJto6fK3/722Y2b/4jQ4aMalBeXb2Ffv1O/GC5X79Sqqu3sGPHFvr3b1i+Y8cWjjvuZC6++NvMmTODJ564k4EDh3HmmRfk7Dw6pGOOgdra8Lq2NiwD9OwJNTX169XUQK9eDbft1avpOj17tr7fZ56Bj340dCtddFHoFnTP+Gl1GCecAO+8E16/8w4cf3x4PXAgvPlm/XpVVaGspfL27vexx8J6110Hv/xlaIFt3Zq588wxhVJuneDubwMkvh/f0opmNt3MVpvZ6oqKipxVMB3799dy111f5qtf/Sk9ejT8pefN/rKyZsst8df2Zz97Dfv27Wb58tlMmfLjbFS5ODTXeslEeBw8GLr7pk6FlSvDX/zSVEv//u29Lq1t/81vwq23wnvvwSOPpL7PCCmUIuXuFe4+wt1HTJ8e3zjeoUMHueuuL3PuuVMYOfLSJu+HFlD9X3U7dlTRt++H6d+/lHffbVoO8N57e9mxI3Qn7d9fm+UzKAB79tR3y5WUhGVo2jLq1Qt27264bWvrtLRfCH/F79tX36oqZlu3hu4yCN+3bQuvq6rgxPreAEpL4a23Wi5v734htJgOHw7XpwN3qar7LvehtNXMBgAkvm/L8fEzwt2pqJjGwIGn88Uv3tzsOh//+MU8//xDuDsbN/6e7t1707fvAM4880L+9Kdl1NZWU1tbzZ/+tIwzz7wQgPnzv825505h0qRZ/OpXX8/lKXVMGzbA8OHh9fDh8Npr4fVrr9WXl5aGmXO1jUK+thYOHAjvN96+pf327g3nnAOzZ4dJEc11PRWTRYvgysTM0SuvhIUL68unTg2vR42CXbtC99rSpXDBBWEsqE+f8Hrp0vbvt3NnmDsXrrgC1q+Hm5v/P9lRFHso5XpK+CLgSuCHie8Lc3z8jNiw4UVeeOH/cuKJZ3DrreGX1+WX/xPvvvtXAL7whRkMH34Ra9cu4aabhtKtWw++8Y25AJSU9GPixNu5/fZPADBx4ncoKenH+vXPUlm5iu9+90U6derMqlWPsmLFXMaMuTo/JxmbSZPCWE6PHuGXzooVYfD98svh7LPDL6gFC8K6GzeGmVs33lg/JbzOjBkhVAAefzwMknftGrbZuDGUt7TfCRNg2bLQolq4MEwnr6hIew5vh/TrX8OYMXDssWFcZ+ZM+OEPw7/NtGnw17+GafQAS5aEMbdNm8LU7asTP8PV1XDHHbBqVVieNau+C/SXvwzXZc2a9Pf7j/8YrtkLL4SJKatWwRNP1P8x0YHoNkNgzY99ZGDHZvOBMcCxwFZgJvAYsAA4CfgrcJm7N54M0RwHmD8/K1WVFE2enLQwc2be6lH0ysvrX3fgrqqCUDdW5p6RC3HSSSP87/9+dcrr33CDrXH3EZk4diyy1lJy98ktvPX5bB1TRKSjK/aWku7oICISCXXfKZRERKKiUBIRkSiopaRQEhGJikJJRESikc9QMrNjgPuAA8AKd//XXNch2js6iIgUm2zc0aG5JzYkysea2QYz22RmdTfHvhT4jbt/Hbg4oyeXIoWSiEhEsnBHh3k0emKDmXUG7gXGAcOAyWY2DCgF6u6D9n4mziddCiURkUhko6XUwhMbRgKb3L3S3Q8AjxCe4lBFCCbIUz4olEREIpJmKB1b9zSFxFeqd68eSH2LCEIYDQT+Hfiymd0PLM7keaVKEx1ERCKS5kSH7W28zVBzt0Vyd98D5PWGmwolEZFI5PBzSlVA0nNAKAWaeY5I7qn7TkQkIml23/U2swoz+1Kah1kFlJnZYDM7CvgK4SkOeaeWkohIJNrQUtrl7q2OIyU/scHMqoCZ7v6AmV0PLAU6A3Pc/dW21TqzFEoiIhHJdPddS09scPclwJLMHq391H0nIhKRHHXfRUstJRGRSGSj+66jUSiJiEREN2QVEZEo6NEVGlMSEYmKxpRERCQaGlMSEZEoqPtOoSQiEpViDyWNKYmIRKINj67QmJKIiGSPxpRERCQaxd59p1ASEYmEJjoolEREolLsoaSJDiIikdBEB7WURESiookOIiISjWLvvlMoiYhEQhMdFEoiIlFRKImISBTUUtLsOxGRqGj2nYiIREGPQ1coiYhEpdi77xRKIiIRUSiJiEgUNNFBoSQiEhWFkoiIREEtJYWSiEhUij2U9DklEZGIFPvnlMzd812HVHSISopIETIDd8vErkpKRvhZZ61Oef3//E9b4+4jMnHsWHSU7ruMXHARkYzL8B/2xd5911FCSUSk4Gmig0JJRCQqCiUREYmGQklERKKg7juFkohIVBRKIiISBbWUFEoiIlFRKImISDSKPZR0myERkUjUdd8V822G1FISEYlIsT8OXS0lKQpm5mZ2Z9Ly/zaz7+axSiJNtKGlVHAUSlIs3gMuNbNj810RkdYolESKwyGgArgp3xURaY1CSaR43AtMMbPe+a6ISHPUfaeJDlJE3L3GzB4CbgD25bs+Is0p1LBJlUJJis1PgT8Ac/NdEZHGdEcHdd9JkXH3HcACYFq+6yLSnGLvvlMoSTG6E9AsPIlSsYeSuu+kKLh7SdLrrUCPPFZHpFnqvlMoiYhERaEkIiJRcIdDh/Jdi/xSKImIREQtJRERiYLGlBRKIiJRUSiJiEgUYm0pmdkpwP8Berv7pGweS59TEhGJSKY/p2Rmc8xsm5m90qh8rJltMLNNZnZLa/tw90p3z8kHztVSEhGJSBZaSvOAe4CH6grMrDPhBsXnA1XAKjNbBHQGftBo+6+5+7aM16oFCiURkWisWQppPfPraDNbnbRc4e4VySu4+3NmNqjRdiOBTe5eCWBmjwAT3P0HwPj06505CiURkUi4+9gcHWog8GbSchUwqqWVzaw/8H3gY2Z2ayK8skKhJCJSfKyZMm9pZXd/F5iRverU00QHEZHiUwWcmLRcCryVp7o0oFASESk+q4AyMxtsZkcBXwEW5blOgEJJRKSgmdl84HfAR8ysysymufsh4HpgKbAeWODur+aznnXMvcVuRBERkZxSS0lERKKhUBIRkWgolEREJBoKJRERiYZCSUREoqFQEhGRaCiUREQkGgolERGJxn8DGyqF63oHKN0AAAAASUVORK5CYII=\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "import numpy\n",
+ "import matplotlib\n",
+ "import matplotlib.pyplot as plt\n",
+ "from matplotlib.colors import LogNorm\n",
+ "\n",
+ "\n",
+ "def heatmap(data, row_labels, col_labels, ax=None,\n",
+ " cbar_kw={}, cbarlabel=\"\", **kwargs):\n",
+ " \"\"\"\n",
+ " Create a heatmap from a numpy array and two lists of labels.\n",
+ "\n",
+ " Parameters\n",
+ " ----------\n",
+ " data\n",
+ " A 2D numpy array of shape (N, M).\n",
+ " row_labels\n",
+ " A list or array of length N with the labels for the rows.\n",
+ " col_labels\n",
+ " A list or array of length M with the labels for the columns.\n",
+ " ax\n",
+ " A `matplotlib.axes.Axes` instance to which the heatmap is plotted. If\n",
+ " not provided, use current axes or create a new one. Optional.\n",
+ " cbar_kw\n",
+ " A dictionary with arguments to `matplotlib.Figure.colorbar`. Optional.\n",
+ " cbarlabel\n",
+ " The label for the colorbar. Optional.\n",
+ " **kwargs\n",
+ " All other arguments are forwarded to `imshow`.\n",
+ " \"\"\"\n",
+ "\n",
+ " if not ax:\n",
+ " ax = plt.gca()\n",
+ "\n",
+ " # Plot the heatmap\n",
+ " im = ax.imshow(data, **kwargs)\n",
+ "\n",
+ " # Create colorbar\n",
+ " cbar = ax.figure.colorbar(im, ax=ax, **cbar_kw)\n",
+ " cbar.ax.set_ylabel(cbarlabel, rotation=-90, va=\"bottom\")\n",
+ "\n",
+ " # We want to show all ticks...\n",
+ " ax.set_xticks(numpy.arange(data.shape[1]))\n",
+ " ax.set_yticks(numpy.arange(data.shape[0]))\n",
+ " # ... and label them with the respective list entries.\n",
+ " ax.set_xticklabels(col_labels)\n",
+ " ax.set_yticklabels(row_labels)\n",
+ "\n",
+ " # Let the horizontal axes labeling appear on top.\n",
+ " ax.tick_params(top=True, bottom=False,\n",
+ " labeltop=True, labelbottom=False)\n",
+ "\n",
+ " # Rotate the tick labels and set their alignment.\n",
+ " plt.setp(ax.get_xticklabels(), rotation=-30, ha=\"right\",\n",
+ " rotation_mode=\"anchor\")\n",
+ "\n",
+ " # Turn spines off and create white grid.\n",
+ " for edge, spine in ax.spines.items():\n",
+ " spine.set_visible(False)\n",
+ "\n",
+ " ax.set_xticks(numpy.arange(data.shape[1]+1)-.5, minor=True)\n",
+ " ax.set_yticks(numpy.arange(data.shape[0]+1)-.5, minor=True)\n",
+ " ax.grid(which=\"minor\", color=\"w\", linestyle='-', linewidth=3)\n",
+ " ax.tick_params(which=\"minor\", bottom=False, left=False)\n",
+ "\n",
+ " return im, cbar\n",
+ "\n",
+ "\n",
+ "def annotate_heatmap(im, data=None, valfmt=\"{x:.2f}\",\n",
+ " textcolors=[\"black\", \"white\"],\n",
+ " threshold=None, **textkw):\n",
+ " \"\"\"\n",
+ " A function to annotate a heatmap.\n",
+ "\n",
+ " Parameters\n",
+ " ----------\n",
+ " im\n",
+ " The AxesImage to be labeled.\n",
+ " data\n",
+ " Data used to annotate. If None, the image's data is used. Optional.\n",
+ " valfmt\n",
+ " The format of the annotations inside the heatmap. This should either\n",
+ " use the string format method, e.g. \"$ {x:.2f}\", or be a\n",
+ " `matplotlib.ticker.Formatter`. Optional.\n",
+ " textcolors\n",
+ " A list or array of two color specifications. The first is used for\n",
+ " values below a threshold, the second for those above. Optional.\n",
+ " threshold\n",
+ " Value in data units according to which the colors from textcolors are\n",
+ " applied. If None (the default) uses the middle of the colormap as\n",
+ " separation. Optional.\n",
+ " **kwargs\n",
+ " All other arguments are forwarded to each call to `text` used to create\n",
+ " the text labels.\n",
+ " \"\"\"\n",
+ "\n",
+ " if not isinstance(data, (list, numpy.ndarray)):\n",
+ " data = im.get_array()\n",
+ "\n",
+ " # Normalize the threshold to the images color range.\n",
+ " if threshold is not None:\n",
+ " threshold = im.norm(threshold)\n",
+ " else:\n",
+ " threshold = im.norm(data.max())/2.\n",
+ "\n",
+ " kw = dict(horizontalalignment=\"center\",\n",
+ " verticalalignment=\"center\")\n",
+ " kw.update(textkw)\n",
+ "\n",
+ " # Get the formatter in case a string is supplied\n",
+ " if isinstance(valfmt, str):\n",
+ " valfmt = matplotlib.ticker.StrMethodFormatter(valfmt)\n",
+ "\n",
+ " texts = []\n",
+ " for i in range(data.shape[0]):\n",
+ " for j in range(data.shape[1]):\n",
+ " kw.update(color=textcolors[int(im.norm(data[i, j]) > threshold)])\n",
+ " text = im.axes.text(j, i, valfmt(data[i, j], None), **kw)\n",
+ " texts.append(text)\n",
+ "\n",
+ " return texts\n",
+ "\n",
+ "def plot_metric(metric, ax, xlabel=\"N\", ylabel=\"trees\"):\n",
+ " x = numpy.array(list(sorted(set(k[0] for k in metric))))\n",
+ " y = numpy.array(list(sorted(set(k[1] for k in metric)))) \n",
+ " rx = {v: i for i, v in enumerate(x)}\n",
+ " ry = {v: i for i, v in enumerate(y)}\n",
+ "\n",
+ " X, Y = numpy.meshgrid(x, y)\n",
+ " zm = numpy.zeros(X.shape, dtype=numpy.float64)\n",
+ " for k, v in metric.items():\n",
+ " zm[ry[k[1]], rx[k[0]]] = v\n",
+ "\n",
+ " xs = [str(_) for _ in x]\n",
+ " ys = [str(_) for _ in y]\n",
+ " vmin = min(metric.values())\n",
+ " vmax = max(metric.values())\n",
+ " im, cbar = heatmap(zm, ys, xs, ax=ax, cmap=\"bwr\", cbarlabel=\"ratio\",\n",
+ " norm=LogNorm(vmin=vmin, vmax=vmax))\n",
+ " texts = annotate_heatmap(im, valfmt=\"{x:.2f}x\")\n",
+ " ax.set_xlabel(xlabel)\n",
+ " ax.set_ylabel(ylabel)\n",
+ "\n",
+ " \n",
+ "data = {(1, 1): 0.1, (10, 1): 1, (1, 10): 2, (10, 10): 100, (100, 1): 100, (100, 10): 1000}\n",
+ "\n",
+ "fig, ax = plt.subplots()\n",
+ "plot_metric(data, ax)\n",
+ "fig.tight_layout();"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## scikit-learn: T trees vs 1 tree\n",
+ "\n",
+ "Let's do first compare a random forest from *scikit-learn* with 1 tree against multiple trees."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from sklearn.datasets import make_regression\n",
+ "ntest = 1000\n",
+ "X, y = make_regression(n_samples=10000 + ntest, n_features=10, n_informative=5,\n",
+ " n_targets=1, random_state=11)\n",
+ "X_train, X_test, y_train, y_test = X[:-ntest], X[-ntest:], y[:-ntest], y[-ntest:]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 5/5 [00:02<00:00, 1.33it/s]\n"
+ ]
+ }
+ ],
+ "source": [
+ "from sklearn.ensemble import RandomForestRegressor\n",
+ "from tqdm import tqdm\n",
+ "\n",
+ "N = [1, 10, 100, 1000, 10000]\n",
+ "T = [1, 2, 10, 20, 50]\n",
+ "\n",
+ "models = {}\n",
+ "for nt in tqdm(T):\n",
+ " rf = RandomForestRegressor(n_estimators=nt, max_depth=5).fit(X_train, y_train)\n",
+ " models[nt] = rf"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 5/5 [01:20<00:00, 19.35s/it]\n"
+ ]
+ },
+ {
+ "data": {
+ "text/plain": [
+ "[((1, 1), 0.9760457855545297),\n",
+ " ((10, 1), 0.9147578680294024),\n",
+ " ((100, 1), 0.7756775134240294)]"
+ ]
+ },
+ "execution_count": 7,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "import sklearn\n",
+ "from mlprodict.onnxrt.validate.validate_benchmark import benchmark_fct\n",
+ "\n",
+ "def benchmark(X, fct1, fct2, N, repeat=10, number=20):\n",
+ " \n",
+ " def ti(r, n):\n",
+ " if n <= 1:\n",
+ " return 40 * r\n",
+ " if n <= 10:\n",
+ " return 10 * r\n",
+ " if n <= 100:\n",
+ " return 4 * r\n",
+ " if n <= 1000:\n",
+ " return r\n",
+ " return r // 2\n",
+ " \n",
+ " with sklearn.config_context(assume_finite=True):\n",
+ " # to warm up the engine\n",
+ " time_kwargs = {n: dict(repeat=10, number=10) for n in N}\n",
+ " benchmark_fct(fct1, X, time_kwargs=time_kwargs, skip_long_test=False)\n",
+ " benchmark_fct(fct2, X, time_kwargs=time_kwargs, skip_long_test=False)\n",
+ " # real measure\n",
+ " time_kwargs = {n: dict(repeat=ti(repeat, n), number=number) for n in N}\n",
+ " res1 = benchmark_fct(fct1, X, time_kwargs=time_kwargs, skip_long_test=False)\n",
+ " res2 = benchmark_fct(fct2, X, time_kwargs=time_kwargs, skip_long_test=False)\n",
+ " res = {}\n",
+ " for r in sorted(res1):\n",
+ " r1 = res1[r]\n",
+ " r2 = res2[r]\n",
+ " ratio = r2['total'] / r1['total']\n",
+ " res[r] = ratio\n",
+ " return res\n",
+ "\n",
+ "\n",
+ "def tree_benchmark(X, fct1, fct2, T, N, repeat=20, number=10):\n",
+ " bench = {}\n",
+ " for t in tqdm(T):\n",
+ " r = benchmark(X, fct1(t), fct2(t), N, repeat=repeat, number=number)\n",
+ " for n, v in r.items():\n",
+ " bench[n, t] = v\n",
+ " return bench\n",
+ "\n",
+ "bench = tree_benchmark(X_test.astype(numpy.float32),\n",
+ " lambda t: models[1].predict,\n",
+ " lambda t: models[t].predict, T, N)\n",
+ "\n",
+ "list(bench.items())[:3]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "fig, ax = plt.subplots()\n",
+ "plot_metric(bench, ax)\n",
+ "fig.tight_layout();"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "As expected, all ratio on first line are close to 1 since both models are the same. fourth line, second column (T=20, N=10) means a random forest with 20 trees is around 5 times slower to compute the predictions of 10 observations in a batch compare to a random forest with 1 tree."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## scikit-learn against onnxuntime"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from skl2onnx import to_onnx\n",
+ "X32 = X_test.astype(numpy.float32)\n",
+ "models_onnx = {t: to_onnx(m, X32[:1]) for t, m in models.items()}"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from onnxruntime import InferenceSession\n",
+ "sess_models = {t: InferenceSession(mo.SerializeToString()) for t, mo in models_onnx.items()}"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 5/5 [01:27<00:00, 21.10s/it]\n"
+ ]
+ }
+ ],
+ "source": [
+ "bench_ort = tree_benchmark(X_test.astype(numpy.float32),\n",
+ " lambda t: models[t].predict,\n",
+ " lambda t: (lambda x, t_=t, se=sess_models: se[t_].run(None, {'X': x})),\n",
+ " T, N)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "fig, ax = plt.subplots()\n",
+ "plot_metric(bench_ort, ax)\n",
+ "ax.set_title(\"scikit-learn vs onnxruntime\\n < 1 means onnxruntime is faster\")\n",
+ "fig.tight_layout();"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "'1.1.997'"
+ ]
+ },
+ "execution_count": 13,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "from onnxruntime import __version__ as ort_version\n",
+ "ort_version"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We clearly see this version of onnxruntime is fast for small batches, still faster but not that much for big batches."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Implementation details for mlrodict runtime\n",
+ "\n",
+ "The runtime implemented in [mlprodict]() mostly relies on two files:\n",
+ "* [op_tree_ensemble_common_p_agg_.hpp](https://github.com/sdpython/mlprodict/blob/master/mlprodict/onnxrt/ops_cpu/op_tree_ensemble_common_p_agg_.hpp)\n",
+ "* [op_tree_ensemble_common_p_.hpp](https://github.com/sdpython/mlprodict/blob/master/mlprodict/onnxrt/ops_cpu/op_tree_ensemble_common_p_.hpp)\n",
+ "\n",
+ "The runtime builds a tree structure, computes the output of every tree and then agregates them. The implementation distringuishes when the batch size contains only 1 observations or many. It parallelizes on the following conditions:\n",
+ "* if the batch size $N \\geqslant N_0$, it then parallizes per observation, asuming every one is independant,\n",
+ "* if the batch size $N = 1$ and the number of trees $T \\geqslant T_0$, it then parallizes per tree."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## scikit-learn against mlprodict, no parallelisation"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from mlprodict.onnxrt import OnnxInference\n",
+ "oinf_models = {t: OnnxInference(mo, runtime=\"python_compiled\") for t, mo in models_onnx.items()}"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Let's disable the parallelisation."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "for _, oinf in oinf_models.items():\n",
+ " oinf.sequence_[0].ops_.rt_.omp_tree_ = 10000000\n",
+ " oinf.sequence_[0].ops_.rt_.omp_N_ = 10000000"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 5/5 [01:14<00:00, 18.38s/it]\n"
+ ]
+ }
+ ],
+ "source": [
+ "bench_mlp = tree_benchmark(X_test.astype(numpy.float32),\n",
+ " lambda t: models[t].predict,\n",
+ " lambda t: (lambda x, t_=t, oi=oinf_models: oi[t_].run({'X': x})),\n",
+ " T, N)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 16,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "fig, ax = plt.subplots()\n",
+ "plot_metric(bench_mlp, ax)\n",
+ "ax.set_title(\"scikit-learn vs mlprodict\\n < 1 means mlprodict is faster\")\n",
+ "fig.tight_layout();"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 17,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "'0.3'"
+ ]
+ },
+ "execution_count": 18,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "from mlprodict import __version__ as mlp_version\n",
+ "mlp_version"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "This implementation seems to be faster. And with parallelisation."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 18,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "for _, oinf in oinf_models.items():\n",
+ " oinf.sequence_[0].ops_.rt_.omp_tree_ = 2\n",
+ " oinf.sequence_[0].ops_.rt_.omp_N_ = 2"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 19,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 5/5 [01:09<00:00, 17.04s/it]\n"
+ ]
+ }
+ ],
+ "source": [
+ "bench_mlp_para = tree_benchmark(X_test.astype(numpy.float32),\n",
+ " lambda t: models[t].predict,\n",
+ " lambda t: (lambda x, t_=t, oi=oinf_models: oi[t_].run({'X': x})),\n",
+ " T, N)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 20,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/png": "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MQsEIC0tv9LMi89i8v3gmzYtus4xx5iiS001xffbb6asA2nTBhITbX/DBjsH2H3bts32ffc0Ls6U6BVXQM2alnfhhcEKvSBOPBE2boQtWyArCz77DM49N7jMokV2HoAffoDmzf153brZuRcs8Ke1bAnz55sSFzFlevrphctRFvgso1DbUUalXJGqLhCRdiWpu3v3VuLiWh8+bty4FevXLw5ZJjIyijp16pOauot69fwRFxYtmk779j2pUaMmTZq05bLLRvPvf99Op059ad26Cz17nle4IDVq2I/dR2amKahAoqP93TLwd418D3Z8vLWze7dZTpmZ1j1p29aUSnq6PdyFERXlV0S+c0RHB5eJjPQrPDBl4VM0UVH2MObmwt69Zrnk5JhiadTIZMrK8j+8oahTx2T2kZZmCiqQunX9SlHV2q5Z066/bVtTYHXrQuPGpoh27rSu3mmnWddy797g7lRBNGtmVp6P5GTo2TN0+auvNkUD9vA//DCMGmXn9LF1K4wbB089BT/+aNbwN98ULkdZcRRaQKEI2ysVkeEislRElk6YMOFwesHB4IJjWhVVZvPmNbz99mj+/Ofxh9POPXcYhw6lMnv2OG6++fnSil84IvawbdgAP/1kloHPAtq1y36AxxwDSUnlK0dOjj1oyclmucXFmWzg9+XExFheSShu1/OXX0yRXXyx+Zy2bzfl6MurUQOOOw6WLClbOS69FLp3h/He7+CGG8yPFajMfEydaory+uvhySdLJseR4iyj8EBVJwA+LXT419S4cSt27txyuNyuXUmHu155y8TFtSInJ5u0tH3ExpqDd+fOJJ555lLuvnsyzZsfe7hORkYau3bZw3/o0AFq1y6ie5SVFeybiY4OtpTA/vkD030WSmamWTw+a2XfPrMsUlPtB+izbCIi/A9lKLKzg3+Yea0g8FtkvvTAdn2fmZnWVo0ati/i7y5GRORvMy9pacGWYZ06lhbIwYOm3NLS/NeZkWF5gT6aiy7yO+EjI/3tRkXlv8d5+f334G5X8+b5XyyAWT4jR8JVV/mt1169zI81dKjf93bwIDz7rFmzvnbr1g22AssTZxmFLx079iE5eT0pKRvIyspk4cKpnHTSkKAyJ500hK+/fhuA776bRvfu/RERDhzYyxNPXMgf//g0xx9/WlCdt98ezRlnXM911z3G66/fVrQgBw/a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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "fig, ax = plt.subplots()\n",
+ "plot_metric(bench_mlp_para, ax)\n",
+ "ax.set_title(\"scikit-learn vs mlprodict\\n < 1 means mlprodict is faster\\nparallelisation\")\n",
+ "fig.tight_layout();"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Parallelisation does improve the computation time when N is big. Let's compare with and without parallisation."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 21,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "bench_para = {}\n",
+ "for k, v in bench_mlp.items():\n",
+ " bench_para[k] = bench_mlp_para[k] / v"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 22,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "fig, ax = plt.subplots()\n",
+ "plot_metric(bench_para, ax)\n",
+ "ax.set_title(\"mlprodict vs mlprodict parallelized\\n < 1 means parallelisation is faster\")\n",
+ "fig.tight_layout();"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Parallisation per trees does not seem to be efficient. Let's confirm with a proper benchmark."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 23,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 5/5 [00:10<00:00, 2.56s/it]\n"
+ ]
+ }
+ ],
+ "source": [
+ "for _, oinf in oinf_models.items():\n",
+ " oinf.sequence_[0].ops_.rt_.omp_tree_ = 1000000\n",
+ " oinf.sequence_[0].ops_.rt_.omp_N_ = 1000000\n",
+ "\n",
+ "oinf_models_para = {t: OnnxInference(mo, runtime=\"python_compiled\") for t, mo in models_onnx.items()}\n",
+ "for _, oinf in oinf_models_para.items():\n",
+ " oinf.sequence_[0].ops_.rt_.omp_tree_ = 2\n",
+ " oinf.sequence_[0].ops_.rt_.omp_N_ = 2\n",
+ "\n",
+ "bench_mlp_para = tree_benchmark(X_test.astype(numpy.float32),\n",
+ " lambda t: (lambda x, t_=t, oi=oinf_models: oi[t_].run({'X': x})),\n",
+ " lambda t: (lambda x, t_=t, oi=oinf_models_para: oi[t_].run({'X': x})),\n",
+ " T, N)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 24,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "fig, ax = plt.subplots()\n",
+ "plot_metric(bench_mlp_para, ax)\n",
+ "ax.set_title(\"mlprodict vs mlprodict parallelized\\n < 1 means parallelisation is faster\\nsame baseline\")\n",
+ "fig.tight_layout();"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "It should be run on different machines. On the current one, parallelisation per trees (when N=1) does not seem to help. Parallisation for a small number of observations does not seem to help either. So we need to find some threshold."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 25,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.7.2"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
\ No newline at end of file