Skip to content
Snippets Groups Projects
test_basic_usage_llvm.ipynb 30.2 KiB
Newer Older
{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# pystencils - LLVM generation\n",
    "The generation of LLVM code is simliar but not identical as seen with the C++ version. For the generation itself a python module ``llvmlite`` is used. This module provides the necessary support and bindings for LLVM. In order to generate from the AST to llvm, the AST needs to be transformed to support type conversions. This is the biggest difference to the C++ version. C++ doesn't need that since the language itself handles the casts.\n",
    "\n",
    "In this example a simple weighted Jacobi kernel is generated, so the focus remains on the part of LLVM generation."
   ]
  },
Michael Kuron's avatar
Michael Kuron committed
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pytest\n",
    "pytest.importorskip('llvmlite')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import sympy as sp\n",
    "import numpy as np\n",
    "import ctypes\n",
    "from pystencils import Field, Assignment\n",
    "from pystencils import create_kernel\n",
    "from pystencils.display_utils import to_dot\n",
    "\n",
    "sp.init_printing()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The numpy arrays (with inital values) create *Field*s for the update Rule. Later those arrays are used for the computation itself."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "src_arr = np.zeros((30, 20))\n",
    "src_arr[0,:] = 1.0\n",
    "src_arr[:,0] = 1.0\n",
    "dst_arr = src_arr.copy()\n",
    "\n",
    "src_field = Field.create_from_numpy_array('src', src_arr)\n",
    "dst_field = Field.create_from_numpy_array('dst', dst_arr)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Using the *Field* objects and the additional *Symbol* $\\omega$ for the weight the update rule is specified as a *sympy* equation."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
Markus Holzer's avatar
Markus Holzer committed
      "image/png": "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\n",
      "text/latex": [
       "$\\displaystyle {{dst}_{(0,0)}} \\leftarrow {{src}_{(0,0)}} \\left(1.0 - \\omega\\right) + \\frac{\\omega \\left({{src}_{(1,0)}} + {{src}_{(0,1)}} + {{src}_{(0,-1)}} + {{src}_{(-1,0)}}\\right)}{4}$"
      ],
Markus Holzer's avatar
Markus Holzer committed
       "                           ω⋅(src_E + src_N + src_S + src_W)\n",
       "dst_C := src_C⋅(1.0 - ω) + ─────────────────────────────────\n",
       "                                           4                "
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "omega = sp.symbols(\"omega\")\n",
    "update_rule = Assignment(dst_field[0,0], omega * (src_field[0,1] + src_field[0,-1] + src_field[1,0] + src_field[-1,0]) / 4\n",
    "                   + (1.-omega)*src_field[0,0])\n",
    "update_rule"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "With this update rule an abstract syntax tree (AST) can be created. This AST can be used to print the LLVM code. The creation follows the same routines as the C++ version does. However at the end there are two more steps. In order to generate LLVM, type casting and pointer arithmetic had to be introduced (which C++ does for you)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
Markus Holzer's avatar
Markus Holzer committed
      "KernelFunction kernel([_data_dst, _data_src, omega])\n",
      "\tBlock for(ctr_0=1; ctr_0<29; ctr_0+=1)\n",
Markus Holzer's avatar
Markus Holzer committed
      "\t\tBlock _data_dst_00 ← pointer_arithmetic_func(_data_dst, 20*ctr_0)\n",
      "\t\t_data_src_00 ← pointer_arithmetic_func(_data_src, 20*ctr_0)\n",
      "\t\t_data_src_01 ← pointer_arithmetic_func(_data_src, 20*ctr_0 + 20)\n",
      "\t\t_data_src_0m1 ← pointer_arithmetic_func(_data_src, 20*ctr_0 - 20)\n",
      "\t\tfor(ctr_1=1; ctr_1<19; ctr_1+=1)\n",
Markus Holzer's avatar
Markus Holzer committed
      "\t\t\tBlock _data_dst_00[ctr_1] ← omega*(_data_src_00[ctr_1 + 1] + _data_src_00[ctr_1 - 1] + _data_src_01[ctr_1] + _data_src_0m1[ctr_1])*cast_func(1/4, double) + (omega*cast_func(-1, double) + cast_func(1.0, double))*_data_src_00[ctr_1]\n",
      "\t\t\n",
      "\t\n",
      "\n"
     ]
    }
   ],
   "source": [
    "ast = create_kernel([update_rule], target='llvm')\n",
    "print(str(ast))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It is possible to examine the AST further."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
       "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
       " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
Markus Holzer's avatar
Markus Holzer committed
       "<!-- Generated by graphviz version 2.40.1 (20161225.0304)\n",
       " -->\n",
       "<!-- Title: %3 Pages: 1 -->\n",
Markus Holzer's avatar
Markus Holzer committed
       "<svg width=\"864pt\" height=\"476pt\"\n",
       " viewBox=\"0.00 0.00 864.48 476.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
       "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 472)\">\n",
       "<title>%3</title>\n",
Markus Holzer's avatar
Markus Holzer committed
       "<polygon fill=\"#ffffff\" stroke=\"transparent\" points=\"-4,4 -4,-472 860.4844,-472 860.4844,4 -4,4\"/>\n",
       "<!-- 139792163067600 -->\n",
       "<g id=\"node1\" class=\"node\">\n",
       "<title>139792163067600</title>\n",
       "<ellipse fill=\"#a056db\" stroke=\"#000000\" cx=\"396.1436\" cy=\"-450\" rx=\"145.6742\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"396.1436\" y=\"-446.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">Func: kernel (dst,src,omega)</text>\n",
Markus Holzer's avatar
Markus Holzer committed
       "<!-- 139791989624336 -->\n",
       "<g id=\"node11\" class=\"node\">\n",
       "<title>139791989624336</title>\n",
       "<ellipse fill=\"#dbc256\" stroke=\"#000000\" cx=\"396.1436\" cy=\"-378\" rx=\"37.0935\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"396.1436\" y=\"-374.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">Block</text>\n",
Markus Holzer's avatar
Markus Holzer committed
       "<!-- 139792163067600&#45;&gt;139791989624336 -->\n",
       "<g id=\"edge10\" class=\"edge\">\n",
       "<title>139792163067600&#45;&gt;139791989624336</title>\n",
       "<path fill=\"none\" stroke=\"#000000\" d=\"M396.1436,-431.8314C396.1436,-424.131 396.1436,-414.9743 396.1436,-406.4166\"/>\n",
       "<polygon fill=\"#000000\" stroke=\"#000000\" points=\"399.6437,-406.4132 396.1436,-396.4133 392.6437,-406.4133 399.6437,-406.4132\"/>\n",
Markus Holzer's avatar
Markus Holzer committed
       "<!-- 139791989623376 -->\n",
       "<g id=\"node2\" class=\"node\">\n",
       "<title>139791989623376</title>\n",
       "<ellipse fill=\"#3498db\" stroke=\"#000000\" cx=\"396.1436\" cy=\"-306\" rx=\"86.3847\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"396.1436\" y=\"-302.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">Loop over dim 0</text>\n",
Markus Holzer's avatar
Markus Holzer committed
       "<!-- 139792050742160 -->\n",
       "<g id=\"node10\" class=\"node\">\n",
       "<title>139792050742160</title>\n",
       "<ellipse fill=\"#dbc256\" stroke=\"#000000\" cx=\"396.1436\" cy=\"-234\" rx=\"37.0935\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"396.1436\" y=\"-230.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">Block</text>\n",
Markus Holzer's avatar
Markus Holzer committed
       "<!-- 139791989623376&#45;&gt;139792050742160 -->\n",
       "<g id=\"edge8\" class=\"edge\">\n",
       "<title>139791989623376&#45;&gt;139792050742160</title>\n",
       "<path fill=\"none\" stroke=\"#000000\" d=\"M396.1436,-287.8314C396.1436,-280.131 396.1436,-270.9743 396.1436,-262.4166\"/>\n",
       "<polygon fill=\"#000000\" stroke=\"#000000\" points=\"399.6437,-262.4132 396.1436,-252.4133 392.6437,-262.4133 399.6437,-262.4132\"/>\n",
Markus Holzer's avatar
Markus Holzer committed
       "<!-- 139791989188432 -->\n",
       "<g id=\"node3\" class=\"node\">\n",
       "<title>139791989188432</title>\n",
       "<ellipse fill=\"#56db7f\" stroke=\"#000000\" cx=\"72.1436\" cy=\"-162\" rx=\"72.2875\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"72.1436\" y=\"-158.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">_data_dst_00</text>\n",
Markus Holzer's avatar
Markus Holzer committed
       "<!-- 139791989188752 -->\n",
       "<g id=\"node4\" class=\"node\">\n",
       "<title>139791989188752</title>\n",
       "<ellipse fill=\"#56db7f\" stroke=\"#000000\" cx=\"234.1436\" cy=\"-162\" rx=\"72.2875\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"234.1436\" y=\"-158.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">_data_src_00</text>\n",
Markus Holzer's avatar
Markus Holzer committed
       "<!-- 139791989189072 -->\n",
       "<g id=\"node5\" class=\"node\">\n",
       "<title>139791989189072</title>\n",
       "<ellipse fill=\"#56db7f\" stroke=\"#000000\" cx=\"396.1436\" cy=\"-162\" rx=\"72.2875\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"396.1436\" y=\"-158.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">_data_src_01</text>\n",
Markus Holzer's avatar
Markus Holzer committed
       "<!-- 139791989189456 -->\n",
       "<g id=\"node6\" class=\"node\">\n",
       "<title>139791989189456</title>\n",
       "<ellipse fill=\"#56db7f\" stroke=\"#000000\" cx=\"567.1436\" cy=\"-162\" rx=\"81.4863\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"567.1436\" y=\"-158.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">_data_src_0m1</text>\n",
Markus Holzer's avatar
Markus Holzer committed
       "<!-- 139792198596368 -->\n",
       "<g id=\"node7\" class=\"node\">\n",
       "<title>139792198596368</title>\n",
       "<ellipse fill=\"#3498db\" stroke=\"#000000\" cx=\"753.1436\" cy=\"-162\" rx=\"86.3847\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"753.1436\" y=\"-158.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">Loop over dim 1</text>\n",
Markus Holzer's avatar
Markus Holzer committed
       "<!-- 139792198655632 -->\n",
       "<g id=\"node9\" class=\"node\">\n",
       "<title>139792198655632</title>\n",
       "<ellipse fill=\"#dbc256\" stroke=\"#000000\" cx=\"753.1436\" cy=\"-90\" rx=\"37.0935\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"753.1436\" y=\"-86.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">Block</text>\n",
Markus Holzer's avatar
Markus Holzer committed
       "<!-- 139792198596368&#45;&gt;139792198655632 -->\n",
       "<g id=\"edge2\" class=\"edge\">\n",
       "<title>139792198596368&#45;&gt;139792198655632</title>\n",
       "<path fill=\"none\" stroke=\"#000000\" d=\"M753.1436,-143.8314C753.1436,-136.131 753.1436,-126.9743 753.1436,-118.4166\"/>\n",
       "<polygon fill=\"#000000\" stroke=\"#000000\" points=\"756.6437,-118.4132 753.1436,-108.4133 749.6437,-118.4133 756.6437,-118.4132\"/>\n",
Markus Holzer's avatar
Markus Holzer committed
       "<!-- 139791989208464 -->\n",
       "<g id=\"node8\" class=\"node\">\n",
       "<title>139791989208464</title>\n",
       "<ellipse fill=\"#56db7f\" stroke=\"#000000\" cx=\"753.1436\" cy=\"-18\" rx=\"103.1819\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"753.1436\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">_data_dst_00[ctr_1]</text>\n",
Markus Holzer's avatar
Markus Holzer committed
       "<!-- 139792198655632&#45;&gt;139791989208464 -->\n",
       "<g id=\"edge1\" class=\"edge\">\n",
       "<title>139792198655632&#45;&gt;139791989208464</title>\n",
       "<path fill=\"none\" stroke=\"#000000\" d=\"M753.1436,-71.8314C753.1436,-64.131 753.1436,-54.9743 753.1436,-46.4166\"/>\n",
       "<polygon fill=\"#000000\" stroke=\"#000000\" points=\"756.6437,-46.4132 753.1436,-36.4133 749.6437,-46.4133 756.6437,-46.4132\"/>\n",
Markus Holzer's avatar
Markus Holzer committed
       "<!-- 139792050742160&#45;&gt;139791989188432 -->\n",
       "<g id=\"edge3\" class=\"edge\">\n",
       "<title>139792050742160&#45;&gt;139791989188432</title>\n",
       "<path fill=\"none\" stroke=\"#000000\" d=\"M362.3868,-226.4985C309.0457,-214.6449 204.358,-191.381 136.3723,-176.2731\"/>\n",
       "<polygon fill=\"#000000\" stroke=\"#000000\" points=\"136.7255,-172.7662 126.2043,-174.0135 135.2069,-179.5995 136.7255,-172.7662\"/>\n",
Markus Holzer's avatar
Markus Holzer committed
       "<!-- 139792050742160&#45;&gt;139791989188752 -->\n",
       "<g id=\"edge4\" class=\"edge\">\n",
       "<title>139792050742160&#45;&gt;139791989188752</title>\n",
       "<path fill=\"none\" stroke=\"#000000\" d=\"M368.6625,-221.7862C344.1691,-210.9002 307.8582,-194.7621 279.1334,-181.9955\"/>\n",
       "<polygon fill=\"#000000\" stroke=\"#000000\" points=\"280.2705,-178.6708 269.7108,-177.8077 277.4275,-185.0674 280.2705,-178.6708\"/>\n",
Markus Holzer's avatar
Markus Holzer committed
       "<!-- 139792050742160&#45;&gt;139791989189072 -->\n",
       "<g id=\"edge5\" class=\"edge\">\n",
       "<title>139792050742160&#45;&gt;139791989189072</title>\n",
       "<path fill=\"none\" stroke=\"#000000\" d=\"M396.1436,-215.8314C396.1436,-208.131 396.1436,-198.9743 396.1436,-190.4166\"/>\n",
       "<polygon fill=\"#000000\" stroke=\"#000000\" points=\"399.6437,-190.4132 396.1436,-180.4133 392.6437,-190.4133 399.6437,-190.4132\"/>\n",
Markus Holzer's avatar
Markus Holzer committed
       "<!-- 139792050742160&#45;&gt;139791989189456 -->\n",
       "<g id=\"edge6\" class=\"edge\">\n",
       "<title>139792050742160&#45;&gt;139791989189456</title>\n",
       "<path fill=\"none\" stroke=\"#000000\" d=\"M424.3808,-222.1107C450.343,-211.1792 489.3422,-194.7585 520.0222,-181.8406\"/>\n",
       "<polygon fill=\"#000000\" stroke=\"#000000\" points=\"521.3947,-185.0604 529.2528,-177.954 518.6783,-178.6089 521.3947,-185.0604\"/>\n",
Markus Holzer's avatar
Markus Holzer committed
       "<!-- 139792050742160&#45;&gt;139792198596368 -->\n",
       "<g id=\"edge7\" class=\"edge\">\n",
       "<title>139792050742160&#45;&gt;139792198596368</title>\n",
       "<path fill=\"none\" stroke=\"#000000\" d=\"M430.3743,-227.0963C487.746,-215.5256 604.5075,-191.977 680.7422,-176.602\"/>\n",
       "<polygon fill=\"#000000\" stroke=\"#000000\" points=\"681.6457,-179.9903 690.7564,-174.5823 680.2618,-173.1285 681.6457,-179.9903\"/>\n",
Markus Holzer's avatar
Markus Holzer committed
       "<!-- 139791989624336&#45;&gt;139791989623376 -->\n",
       "<g id=\"edge9\" class=\"edge\">\n",
       "<title>139791989624336&#45;&gt;139791989623376</title>\n",
       "<path fill=\"none\" stroke=\"#000000\" d=\"M396.1436,-359.8314C396.1436,-352.131 396.1436,-342.9743 396.1436,-334.4166\"/>\n",
       "<polygon fill=\"#000000\" stroke=\"#000000\" points=\"399.6437,-334.4132 396.1436,-324.4133 392.6437,-334.4133 399.6437,-334.4132\"/>\n",
       "</g>\n",
       "</g>\n",
       "</svg>\n"
      ],
      "text/plain": [
Markus Holzer's avatar
Markus Holzer committed
       "<graphviz.files.Source at 0x7f23dbdc5c10>"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "to_dot(ast)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "With transformed AST it is now possible to generate and compile the AST into LLVM. Notice that unlike in C++ version, no files are writen to the hard drive (although it is possible).\n",
    "\n",
    "There are multiple ways how to generate and compile the AST. The most simple one is simillar to the C++ version. Using the ``compile()`` function of the generated AST\n",
    "\n",
    "You can also manually create a python function with ``make_python_function``.\n",
    "\n",
    "Another option is obtaining the jit itself with ``generate_and_jit``.\n",
    "The function ``generate_and_jit`` first generates and the compiles the AST.\n",
    "\n",
    "If even more controll is needed, it is possible to use the functions ``generateLLVM`` and ``compileLLVM`` to achieve the same. For further controll, instead of calling ``compileLLVM`` the jit object itself can be created and its necessary functions for the compilation have to be run manually (``parse``, (``optimize``,) ``compile``)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "scrolled": false
   },
   "outputs": [],
   "source": [
    "kernel = ast.compile()\n",
    "\n",
    "#kernel = make_python_function(ast)\n",
    "\n",
    "# Or alternativally\n",
    "#jit = generate_and_jit(ast)\n",
    "# Call: jit('kernel', src_arr, dst_arr)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The compiled function(s) can be used now. Either call the function (with arguments, if not given before) or call the jit object with the function's name and its arguments. Here, numpy arrays are automatically adjusted with ctypes.\n",
    "\n",
    "The functions and arguments can be read as well.\n",
    "\n",
    "**All of the information the jit object has comes from the module which was parsed. If you parse a second module and don't run the compilation step, the module and the compiled code are not the same anymore, thus leading to false information**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "#jit.print_functions()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "for i in range(100):\n",
    "    kernel(src=src_arr, dst=dst_arr, omega=2/3)\n",
    "    src_arr, dst_arr = dst_arr, src_arr\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The output is drawn with matplotlib."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
Markus Holzer's avatar
Markus Holzer committed
      "image/png": "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\n",
Markus Holzer's avatar
Markus Holzer committed
       "<Figure size 432x288 with 1 Axes>"
Markus Holzer's avatar
Markus Holzer committed
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "from matplotlib import cm\n",
    "fig = plt.figure()\n",
    "ax = fig.add_subplot(111)\n",
    "ax.imshow(dst_arr, cmap=cm.jet)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "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",
Markus Holzer's avatar
Markus Holzer committed
   "version": "3.7.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}